hal_flash.c 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. #include "hal_flash.h"
  2. #include "hc32_ll.h"
  3. #define HC32_FLASH_BASE 0x00
  4. #define HC32_SECTOR_SIZE 0x2000//8kb
  5. static uint8_t internal_flash_data[HC32_SECTOR_SIZE];//最多是2K字节
  6. int32_t hc32_flash_read(uint32_t u32Addr, uint8_t *pu8Buff, uint32_t u32Len)
  7. {
  8. return EFM_ReadByte(u32Addr,pu8Buff, u32Len);
  9. }
  10. int32_t hc32_flash_read_sector(uint32_t u32Addr)
  11. {
  12. return EFM_ReadByte(u32Addr,internal_flash_data,sizeof(internal_flash_data));//读取一个扇区的数据/8kb
  13. }
  14. int32_t hc32_flash_write(uint32_t write_addr,uint8_t *buffer,uint32_t number)
  15. {
  16. uint32_t i;
  17. uint32_t sector_page = write_addr/HC32_SECTOR_SIZE;
  18. uint32_t secpos; //扇区地址
  19. uint32_t secoff; //扇区内偏移地址
  20. uint32_t secremain; //扇区内剩余地址
  21. uint32_t offaddr; //去掉0X08000000后的地址
  22. offaddr = write_addr-HC32_FLASH_BASE; //实际偏移地址.
  23. secpos = offaddr/HC32_SECTOR_SIZE; //扇区地址 0~32 for HC32F448MTCI
  24. secoff = (offaddr%HC32_SECTOR_SIZE); //在扇区内的偏移
  25. secremain = HC32_SECTOR_SIZE-secoff; //扇区剩余空间大小
  26. if(number<=secremain)secremain=number; //不大于该扇区范围
  27. LL_PERIPH_WE(LL_PERIPH_GPIO | LL_PERIPH_FCG | LL_PERIPH_PWC_CLK_RMU | LL_PERIPH_EFM | LL_PERIPH_SRAM);
  28. EFM_FWMC_Cmd(ENABLE);
  29. while(1)
  30. {
  31. /*读取当前扇区的数据*/
  32. hc32_flash_read(secpos*HC32_SECTOR_SIZE+HC32_FLASH_BASE,internal_flash_data,sizeof(internal_flash_data));
  33. for(i = 0;i < HC32_SECTOR_SIZE;i++)
  34. {
  35. if(internal_flash_data[i]!=0xff)
  36. break;
  37. }
  38. if(i < secremain)
  39. {
  40. EFM_SingleSectorOperateCmd(sector_page, ENABLE);//解除写保护
  41. EFM_SectorErase(secpos*HC32_SECTOR_SIZE+HC32_FLASH_BASE);
  42. for(i=0;i<secremain;i++)//复制
  43. {
  44. internal_flash_data[secoff+i]=buffer[i];
  45. }
  46. EFM_Program(secpos*HC32_SECTOR_SIZE+HC32_FLASH_BASE, internal_flash_data, sizeof(internal_flash_data));
  47. EFM_SingleSectorOperateCmd(sector_page, DISABLE);
  48. }
  49. else
  50. {
  51. EFM_SingleSectorOperateCmd(sector_page, ENABLE);//解除写保护
  52. EFM_Program(write_addr,buffer,secremain);
  53. EFM_SingleSectorOperateCmd(sector_page, DISABLE);
  54. }
  55. if(number==secremain) break; //写入完成
  56. else
  57. {
  58. secpos++; //扇区地址增1
  59. secoff=0; //偏移位置为0
  60. buffer+=secremain; //指针偏移
  61. write_addr+=secremain;//写地址偏移
  62. number-=secremain; //字节(16位)数递减
  63. if(number>(HC32_SECTOR_SIZE))
  64. secremain=HC32_SECTOR_SIZE;//下一个扇区还是写不完
  65. else
  66. secremain=number;//下一个扇区可以写完了
  67. }
  68. }
  69. EFM_FWMC_Cmd(DISABLE);
  70. LL_PERIPH_WP(LL_PERIPH_GPIO | LL_PERIPH_FCG | LL_PERIPH_PWC_CLK_RMU | LL_PERIPH_EFM | LL_PERIPH_SRAM);
  71. }