小学生
最后登录1970-1-1
在线时间 小时
注册时间2023-1-3
|
目前调试发现的现象:
上位机点击下载,将第一段数据(192个字节)传入到0x08002000(APP所在的地址)。完成写入后,进入HardFault_Handler。
通过烧录器软件读取User Flash,可以看到192个字节数据正常写入。目前感觉是读写Flash的函数出问题
- // 得到FLASH状态
- uint8_t Bsp_FLASH_GetStatus(void)
- {
- uint32_t res;
- res = FLASH->SR;
- if (res & FLASH_SR_BSY)
- return 1;
- // flash出错
- if (res & FLASH_FLAG_ALL_ERR)
- return 2;
- // /* check flash errors */
- // error = (FLASH->SR & FLASH_SR_ERRORS);
- // /* Clear SR register */
- // FLASH->SR = FLASH_SR_CLEAR;
- return 0; // 操作完成
- }
- // 等待操作完成
- // time:要延时的长短
- // 返回值:状态.
- uint8_t Bsp_FLASH_WaitDone(uint16_t time)
- {
- uint8_t res;
- do
- {
- res = Bsp_FLASH_GetStatus();
- if (res != 1)
- break; // 非忙,无需等待了,直接退出.
- delay_us(1);
- time--;
- } while (time);
- if (time == 0)
- res = 0xff; // TIMEOUT
- return res;
- }
- // 擦除页
- // paddr:页地址
- // 返回值:执行情况
- uint8_t Bsp_FLASH_ErasePage(uint32_t paddr)
- {
- uint8_t res = 0;
- res = Bsp_FLASH_WaitDone(0X5FFF); // 等待上次操作结束,>20ms
- if (res == 0)
- {
- std_flash_page_erase(paddr);
- res = Bsp_FLASH_WaitDone(0X5FFF); // 等待操作结束,>20ms
- if (res != 1) // 非忙
- {
- std_flash_set_erase_mode(FLASH_ERASE_DISABLE);
- }
- }
- return res;
- }
- // 在FLASH指定地址写入半字
- // faddr:指定地址(此地址必须为2的倍数!!)
- // dat:要写入的数据
- // 返回值:写入的情况
- uint8_t Bsp_FLASH_WriteHalfWord(uint32_t faddr, uint16_t dat)
- {
- uint8_t res;
- res = Bsp_FLASH_WaitDone(0XFF);
- if (res == 0) // OK
- {
- FLASH->CR |= 1 << 0; // 编程使能
- *(__IO uint16_t *)faddr = dat; // 写入数据
- res = Bsp_FLASH_WaitDone(0XFF); // 等待操作完成
- if (res != 1) // 操作成功
- {
- FLASH->CR &= ~(1 << 0); // 清除PG位.
- }
- }
- return res;
- }
- // 在FLASH指定地址写入
- // faddr:指定地址(此地址必须为2的倍数!!)
- // dat:要写入的数据
- // 返回值:写入的情况
- uint8_t Bsp_FLASH_WriteDoubleWord(uint32_t faddr, uint64_t dat)
- {
- uint8_t res;
- res = Bsp_FLASH_WaitDone(0XFF);
- if (res == 0) // OK
- {
- FLASH->CR |= 1 << 0; // 编程使能
- /* Program first word */
- *(uint32_t *)faddr = (uint32_t)dat;
- /* Barrier to ensure programming is performed in 2 steps, in right order
- (independently of compiler optimization behavior) */
- __ISB();
- /* Program second word */
- *(uint32_t *)(faddr + 4U) = (uint32_t)(dat >> 32U);
- res = Bsp_FLASH_WaitDone(0XFF); // 等待操作完成
- if (res != 1) // 操作成功
- {
- FLASH->CR &= ~(1 << 0); // 清除PG位.
- }
- }
- return res;
- }
- // 读取指定地址的半字(16位数据)
- // faddr:读地址
- // 返回值:对应数据.
- uint16_t Bsp_FLASH_ReadHalfWord(uint32_t faddr)
- {
- return *(__IO uint16_t *)faddr;
- }
- uint64_t Bsp_FLASH_ReadDoubleWord(uint32_t faddr)
- {
- return *(__IO uint64_t *)faddr;
- }
- #if STM32_FLASH_WREN // 如果使能了写
- // 不检查的写入
- // WriteAddr:起始地址
- // pBuffer:数据指针
- // NumToWrite:半字(16位)数
- void Bsp_FLASH_Write_NoCheck(uint32_t WriteAddr, uint64_t *pBuffer, uint16_t NumToWrite)
- {
- uint16_t i;
- for (i = 0; i < NumToWrite; i++)
- {
- Bsp_FLASH_WriteDoubleWord(WriteAddr, pBuffer[i]);
- WriteAddr += 8; // 地址增加2.
- }
- }
- // 从指定地址开始写入指定长度的数据
- // WriteAddr:起始地址(此地址必须为2的倍数!!)
- // pBuffer:数据指针
- // NumToWrite:半字(16位)数(就是要写入的16位数据的个数.)
- // #define STM_SECTOR_SIZE 1024 //字节
- #define STM_SECTOR_SIZE 2048
- #define STM_WRSIZE 8
- uint64_t Bsp_FLASH_BUF[STM_SECTOR_SIZE / STM_WRSIZE]; // 最多是2K字节
- void Bsp_FLASH_Write(uint32_t WriteAddr, uint64_t *pBuffer, uint16_t NumToWrite)
- {
- static uint8_t pre_sector = 0;
- uint32_t secpos; // 扇区地址
- uint16_t secoff; // 扇区内偏移地址(16位字计算)
- uint16_t secremain; // 扇区内剩余地址(16位字计算)
- uint16_t i;
- uint32_t offaddr; // 去掉0X08000000后的地址
- if (WriteAddr < STM32_FLASH_BASE || (WriteAddr >= (STM32_FLASH_BASE + 1024 * STM32_FLASH_SIZE)))
- return; // 非法地址
- std_flash_unlock(); // 解锁
- offaddr = WriteAddr - STM32_FLASH_BASE; // 实际偏移地址.
- secpos = offaddr / STM_SECTOR_SIZE; // 扇区地址 0~127 for STM32F103RBT6
- secoff = (offaddr % STM_SECTOR_SIZE) / STM_WRSIZE; // 在扇区内的偏移(2个字节为基本单位.)
- secremain = STM_SECTOR_SIZE / STM_WRSIZE - secoff; // 扇区剩余空间大小
- if (NumToWrite <= secremain)
- secremain = NumToWrite; // 不大于该扇区范围
- while (1)
- {
- if (secpos != pre_sector)
- {
- pre_sector = secpos;
- Bsp_FLASH_ErasePage(secpos); // 擦除这个扇区
- }
- Bsp_FLASH_Write_NoCheck(WriteAddr, pBuffer, secremain); // 写已经擦除了的,直接写入扇区剩余区间.
- if (NumToWrite == secremain)
- break; // 写入结束了
- else // 写入未结束
- {
- secpos++; // 扇区地址增1
- secoff = 0; // 偏移位置为0
- pBuffer += secremain; // 指针偏移
- WriteAddr += secremain * STM_WRSIZE; // 写地址偏移(16位数据地址,需要*2)
- NumToWrite -= secremain; // 字节(16位)数递减
- if (NumToWrite > (STM_SECTOR_SIZE / STM_WRSIZE))
- secremain = STM_SECTOR_SIZE / STM_WRSIZE; // 下一个扇区还是写不完
- else
- secremain = NumToWrite; // 下一个扇区可以写完了
- }
- };
- std_flash_lock(); // 上锁
- }
- #endif
- // 从指定地址开始读出指定长度的数据
- // ReadAddr:起始地址
- // pBuffer:数据指针
- // NumToWrite:半字(16位)数
- void Bsp_FLASH_Read(uint32_t ReadAddr, uint64_t *pBuffer, uint16_t NumToRead)
- {
- uint16_t i;
- for (i = 0; i < NumToRead; i++)
- {
- pBuffer[i] = Bsp_FLASH_ReadDoubleWord(ReadAddr); // 读取2个字节.
- ReadAddr += 8; // 偏移8个字节.
- }
- }
复制代码
|
|