hal_flash.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. #include "hal_flash.h"
  2. /*********************************************************************
  3. *DEFINITION
  4. */
  5. typedef struct zone_s
  6. {
  7. uint8_t page_num;
  8. uint32_t zone_start_addr;
  9. }zone_t;
  10. /*********************************************************************
  11. * LOCAL VARIABLES
  12. */
  13. static int16_t PageCount = FLASH_PAGE_NUM; //可用页数
  14. static uint32_t zone_used_index = 0; //zone结构体下标
  15. static zone_t zone[FLASH_PAGE_NUM]; //zone结构体
  16. /*********************************************************************
  17. * LOCAL FUNCTIONS
  18. */
  19. /**
  20. @brief 通过区域地址获取区域索引
  21. @param zone_addr[in] - 分配的区域地址
  22. @param zone_index[out] - 返回分配的区域索引
  23. @return 错误代码
  24. */
  25. static uint32_t Zone_GetIndex(uint32_t zone_addr, uint32_t *zone_index)
  26. {
  27. for(int i=0; i < zone_used_index; i++)
  28. {
  29. if( zone[i].zone_start_addr <= zone_addr && (zone[i].zone_start_addr + zone[i].page_num * FLASH_PAGE_SIZE) > zone_addr ){
  30. if(zone_index != NULL)*zone_index = i;
  31. return ZONE_OP_SUCCESS;
  32. }
  33. }
  34. return ZONE_ERROR_NO_INDEX;
  35. }
  36. /*********************************************************************
  37. * PUBLIC FUNCTIONS
  38. */
  39. /**
  40. @brief 初始化一个区域
  41. @param page_size[in] - 该区域使用了几个页
  42. @param zone_start_addr[out] - 返回分配的区域首地址
  43. @return 错误代码
  44. */
  45. uint32_t Zone_Alloca(uint8_t page_num, uint32_t *zone_start_addr)
  46. {
  47. if(page_num <= 0) return ZONE_ERROR_PARAM_PAGE_NUM;
  48. if(PageCount - page_num < 0)return ZONE_ERROR_NO_PAGE;
  49. zone[zone_used_index].page_num = page_num;
  50. if(zone_used_index == 0)zone[zone_used_index].zone_start_addr = FLASH_ZONE_ADDR_1;
  51. else zone[zone_used_index].zone_start_addr = zone[zone_used_index-1].zone_start_addr + FLASH_PAGE_SIZE * zone[zone_used_index-1].page_num;
  52. if(zone_start_addr != NULL)*zone_start_addr = zone[zone_used_index].zone_start_addr;
  53. PageCount -= page_num;
  54. zone_used_index++;
  55. return ZONE_OP_SUCCESS;
  56. }
  57. /**
  58. @brief 读取一个区域中指定位置的数据
  59. @param destination_addr[in] - 读取区域的地址
  60. @param pData[in] - 指向存储的buff
  61. @param dataLen[in] - 读取的长度,单位字节
  62. @return 错误代码
  63. */
  64. uint32_t Zone_Read(uint32_t destination_addr, uint32_t *pData, uint32_t dataLen)
  65. {
  66. uint32_t err_code; //错误代码
  67. uint32_t zone_index; //是否有相对应的区域索引
  68. uint32_t next_zone_addr; //下个区域的首地址
  69. //验证是否申请了对应区域
  70. err_code = Zone_GetIndex(destination_addr, &zone_index);
  71. if(err_code != ZONE_OP_SUCCESS)return err_code;
  72. if(pData != NULL && dataLen != 0)
  73. {
  74. next_zone_addr = zone[zone_index].zone_start_addr + zone[zone_index].page_num * FLASH_PAGE_SIZE;
  75. //不能读到下一个区域
  76. if((destination_addr + dataLen) > next_zone_addr)return ZONE_ERROR_READ_FAIL;
  77. //读取
  78. err_code = Read_N_Byte_flash(destination_addr, pData, dataLen);
  79. if(err_code != FLASH_OP_SUCCESS)return ZONE_ERROR_READ_FAIL;
  80. }
  81. return ZONE_OP_SUCCESS;
  82. }
  83. /**
  84. @brief 往一个区域指定位置写入数据(支持跨页写)
  85. @param destination_addr[in] - 写入区域的地址
  86. @param pData[in] - 指向存储的buff
  87. @param dataLen[in] - 写入的长度
  88. @return 错误代码
  89. */
  90. uint32_t Zone_Write(uint32_t destination_addr, uint32_t *pData, uint32_t dataLen)
  91. {
  92. uint32_t err_code; //错误代码
  93. uint32_t zone_index; //是否有相对应的区域索引
  94. uint32_t next_zone_addr; //下个区域的首地址
  95. //验证是否申请了对应区域
  96. err_code = Zone_GetIndex(destination_addr, &zone_index);
  97. if(err_code != ZONE_OP_SUCCESS)return err_code;
  98. if(pData != NULL && dataLen != 0)
  99. {
  100. next_zone_addr = zone[zone_index].zone_start_addr + zone[zone_index].page_num * FLASH_PAGE_SIZE;
  101. //不能写到下一个区域
  102. if((destination_addr + dataLen) > next_zone_addr)return ZONE_ERROR_WRITE_FAIL;
  103. //写入
  104. err_code = Write_N_4Byte_flash(destination_addr, pData, dataLen);
  105. if(err_code != FLASH_OP_SUCCESS)return ZONE_ERROR_WRITE_FAIL;
  106. }
  107. return ZONE_OP_SUCCESS;
  108. }
  109. /**
  110. @brief 擦除一个区域
  111. @param zone_start_addr[in] - 分配的区域首地址
  112. @return 错误代码
  113. */
  114. uint32_t Zone_Erase(uint32_t zone_start_addr)
  115. {
  116. uint32_t err_code; //错误代码
  117. uint32_t zone_index; //是否有相对应的区域索引
  118. uint16_t PageNum;
  119. //验证是否申请了对应区域
  120. err_code = Zone_GetIndex(zone_start_addr, &zone_index);
  121. if(err_code != ZONE_OP_SUCCESS)return err_code;
  122. //一页一页擦除
  123. for(uint8_t i = 0; i < zone[zone_index].page_num; i++)
  124. {
  125. //获取输入地址对应的页号
  126. err_code = GetPageNum(zone[zone_index].zone_start_addr + i * FLASH_PAGE_SIZE, &PageNum);
  127. if(err_code != FLASH_OP_SUCCESS)return ZONE_ERROR_ERASE_FAIL;
  128. //根据页号擦除一整页
  129. err_code = Erase_OnePage(PageNum);
  130. if(err_code != FLASH_OP_SUCCESS)return ZONE_ERROR_ERASE_FAIL;
  131. }
  132. return ZONE_OP_SUCCESS;
  133. }
  134. /**
  135. @brief 获取一个区域的总字节大小
  136. @param zone_start_addr[in] - 分配的区域首地址
  137. @param bytes[out] - 返回区域的字节大小
  138. @return 错误代码
  139. */
  140. uint32_t Zone_GetByteSize(uint32_t zone_start_addr, uint32_t *bytes)
  141. {
  142. uint32_t err_code; //错误代码
  143. uint32_t zone_index; //是否有相对应的区域索引
  144. //验证是否申请了对应区域
  145. err_code = Zone_GetIndex(zone_start_addr, &zone_index);
  146. if(err_code != ZONE_OP_SUCCESS)return err_code;
  147. if(bytes != NULL)*bytes = zone[zone_index].page_num * FLASH_PAGE_SIZE;
  148. return ZONE_OP_SUCCESS;
  149. }