/* includes ----------------------------------------------------------*/ #include "flash.h" /* typedef -----------------------------------------------------------*/ /* define ------------------------------------------------------------*/ /* macro -------------------------------------------------------------*/ /* variables ---------------------------------------------------------*/ param_boot s_param_boot = { .jumpAddr = 0x8040C00U, }; /* function prototypes -----------------------------------------------*/ /** * @brief flash读数据 * @param address:读数据的起始地址 read_buf:数据存储区 length:读取的数据长度 * @return HAL_StatusTypeDef */ void FLASH_Read(uint32_t address, uint32_t *read_buf, uint32_t length) { for (uint32_t i = 0; i < length; i++) { read_buf[i] = *(volatile uint32_t*)(address + (i * 4)); // 以字(32位)为单位读取 } } /** * @brief flash按页擦除 * @param app_address address to jump number_of_pages:擦除页的页数 * @return HAL_StatusTypeDef */ HAL_StatusTypeDef FLASH_Erase(uint32_t start_address, uint32_t number_of_pages) { HAL_StatusTypeDef status = HAL_ERROR; FLASH_EraseInitTypeDef EraseInitStruct; uint32_t PageError = 0; // 解锁Flash HAL_FLASH_Unlock(); // 设置擦除参数 EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES; EraseInitStruct.PageAddress = start_address; EraseInitStruct.NbPages = number_of_pages; // 擦除Flash status = HAL_FLASHEx_Erase(&EraseInitStruct, &PageError); // 锁定Flash HAL_FLASH_Lock(); return status; // 返回擦除操作的状态 } /** * @brief flash按字写入 * @param address:写入地址 data:数据 length:长度 * @return HAL_StatusTypeDef */ HAL_StatusTypeDef FLASH_Write(uint32_t address, uint32_t *data, uint32_t length) { HAL_StatusTypeDef status = HAL_OK; // 进入临界区 挂起所有任务 vTaskSuspendAll(); // 解锁Flash HAL_FLASH_Unlock(); // 逐个字节写入数据 for (uint32_t i = 0; i < length; i++) { if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, address, data[i]) == HAL_OK) { // 验证写入的数据 if (*(uint32_t*)address != data[i]) { status = HAL_ERROR; break; } address += 4; // 更新地址(一个字的大小) } else { status = HAL_ERROR; break; } } // 锁定Flash HAL_FLASH_Lock(); // 退出临界区 恢复任务调度 xTaskResumeAll(); return status; // 返回写入操作的状态 } /** * @brief 写参数区跳转地址数据 * @param none * @return HAL_StatusTypeDef */ void Write_paramArea(void){ // 擦除和写入参数 uint32_t start_address = PARAM_ADDRESS; // Flash起始地址 uint32_t number_of_pages = 1; // 假设我们只擦除1页 // 调用擦除函数 if (FLASH_Erase(start_address, number_of_pages) != HAL_OK) { // 擦除失败的处理 } // 调用写入函数 if (FLASH_Write(start_address, (uint32_t*)&s_param_boot, (FLASH_PAGE_SIZE / sizeof(uint32_t))) != HAL_OK) { // 写入失败的处理 } } /** * @brief 参数区数据读取 * @param NONE * @return HAL_StatusTypeDef */ void Read_ParamArea(void) { // 读取结构体中前两个字的数据 FLASH_Read(PARAM_ADDRESS, (uint32_t*)&s_param_boot, sizeof(param_boot) / sizeof(uint32_t)); } /** * @brief 向量重映射 * @param NONE * @return HAL_StatusTypeDef */ void Remap_Vector_Table(void) { __disable_irq(); // 设置向量表到程序运行区 SCB->VTOR = APP1_ADDRESS; __enable_irq(); } /** * @brief 读取96位(或者说是3个32位的字)的唯一ID * @param id: 指向三个uint32_t元素数组的指针作为参数,用来存储读取的唯一设备ID * @return * @note */ void GetUniqueID(uint32_t* id) { if (id != NULL) { for (int i = 0; i < 3; i++) { *id++ = *(UNIQUE_ID_ADDR + i); } } }