英文:
Why should I typecast a 32 bit address to 16 bit to store a 16 bit data
问题
I am working on an STM32 Flash, I came across this function that writes 16-bit data to an address that is 32-bit. Why should I typecast this address like *(__IO uint16_t*)Address = Data;
which expands to *(volatile uint16_t *)Address = Data;
static void FLASH_Program_HalfWord(uint32_t Address, uint16_t Data)
{
/* Check the parameters */
assert_param(IS_FLASH_ADDRESS(Address));
/* If the previous operation is completed, proceed to program the new data */
CLEAR_BIT(FLASH->CR, FLASH_CR_PSIZE);
FLASH->CR |= FLASH_PSIZE_HALF_WORD;
FLASH->CR |= FLASH_CR_PG;
*(__IO uint16_t*)Address = Data;
}
I expect *((uint32_t *)Address) = data
to be sufficient.
英文:
I am working on an STM32 Flash, I came across this function that writes 16-bit data to an address that is 32-bit. Why should I typecast this address like *(__IO uint16_t*)Address = Data;
which expands to *(volatile uint16_t *)Address = Data;
static void FLASH_Program_HalfWord(uint32_t Address, uint16_t Data)
{
/* Check the parameters */
assert_param(IS_FLASH_ADDRESS(Address));
/* If the previous operation is completed, proceed to program the new data */
CLEAR_BIT(FLASH->CR, FLASH_CR_PSIZE);
FLASH->CR |= FLASH_PSIZE_HALF_WORD;
FLASH->CR |= FLASH_CR_PG;
*(__IO uint16_t*)Address = Data;
}
I expect *((uint32_t *)Address) = data
to be sufficient.
答案1
得分: 2
指针是一个内存地址。内存地址本身是32位的。不同之处在于它所指向的数据。当你有一个指向32位整数的指针时,编译器会生成加载和存储32位数据的指令。当你有一个指向16位整数的指针时,编译器会生成加载和存储16位数据的指令。想象一个例子:
MemAdd: 0x100 0x101 0x102 0x103
MemVal: 0xFF 0xFF 0xFF 0xFF
指针: 0x100
如果你执行 *(uint32_t*)(Pointer) = 0x1234
,0x100-0x103的内存将包含 0x00001234
。如果你执行 *(uint16_t*)(Pointer) = 0x1234
,0x100-0x103的内存将包含 0xFFFF1234
。另外两个字节没有被覆盖。
由于你想要向闪存写入半字,你需要告诉编译器生成用于存储16位值的指令。
英文:
Pointer is a memory address. A memory address itself is 32-bit. It is the data it's pointing to that is different. When you have pointer to 32-bit integer, the compiler generates instructions that load and store 32 bits of data at a time. When you have a pointer to 16-bit integer, the compiler generates instructions that load and store 16 bits of data. Imagine example:
MemAdd: 0x100 0x101 0x102 0x103
MemVal: 0xFF 0xFF 0xFF 0xFF
Pointer: 0x100
if you *(uint32_t*)(Pointer) = 0x1234
, the memory at 0x100-0x103 will contain 0x00001234
. If you *(uint16_t*)(Pointer) = 0x1234
, the memory at 0x100-0x103 will contain 0xFFFF1234
. The other two bytes were never overwritten.
Since you want to write half-word to flash, you want to tell the compiler to generate instructions for storing 16-bit value.
答案2
得分: 1
This operation converts it to the pointer to uint16_t
and then dereferences it. It is done to force use of 16 bits write/read instructions in the generated code.
void write16(uint32_t addr, uint16_t val)
{
*(volatile uint16_t *)addr = val;
}
void write8(uint32_t addr, uint16_t val)
{
*(volatile uint8_t *)addr = val;
}
void write32(uint32_t addr, uint16_t val)
{
*(volatile uint32_t *)addr = val;
}
write16:
strh r1, [r0] @ movhi
bx lr
write8:
uxtb r1, r1
strb r1, [r0]
bx lr
write32:
str r1, [r0]
bx lr
When programming flash, it is very important as it is not "normal" write to the memory.
英文:
This operation converts it to the pointer to uint16_t
and then dereferences it. It is done to force use of 16 bits write/read instructions in the generated code.
void write16(uint32_t addr, uint16_t val)
{
*(volatile uint16_t *)addr = val;
}
void write8(uint32_t addr, uint16_t val)
{
*(volatile uint8_t *)addr = val;
}
void write32(uint32_t addr, uint16_t val)
{
*(volatile uint32_t *)addr = val;
}
write16:
strh r1, [r0] @ movhi
bx lr
write8:
uxtb r1, r1
strb r1, [r0]
bx lr
write32:
str r1, [r0]
bx lr
When programing flash it is very important as it is not "normal" write to the memory.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论