//#include "drv_clk.h" #include "drv_wdog.h" #include "drv_flash.h" #include "kit_debug.h" #include "stm32f4xx.h" /* FLASH Keys */ #define FLASH_KEY1 ((uint32_t)0x45670123) #define FLASH_KEY2 ((uint32_t)0xCDEF89AB) #define CR_LOCK_Set KIT_CREAT_BIT(31) #define FLASH_FLAG_BSY KIT_CREAT_BIT(16) /*!< FLASH Busy flag */ #define FLASH_FLAG_EOP KIT_CREAT_BIT(0) /*!< FLASH End of Operation flag */ #define FLASH_FLAG_ERR (KIT_CREAT_BITS(4, 7) | KIT_CREAT_BIT(1)) /*!< FLASH Program error flag */ #define CR_PG_Set KIT_CREAT_BIT(0) #define CR_PER_Set KIT_CREAT_BIT(1) #define CR_SART KIT_CREAT_BIT(16) #define CR_PG_PSIZE KIT_CREAT_BITS(8, 9) #define CR_PG_SNB KIT_CREAT_BITS(3, 7) //#define CR_STRT_Set ((uint32_t)0x00000040) //#define CR_PER_Reset ((uint32_t)0x00001FFD) #define EraseTimeout ((uint32_t)0x02000000) #define ProgramTimeout ((uint32_t)0x00002000) const uint32_t page_start_addr[13] = { 0x08000000, 0x08004000, 0x08008000, 0x0800C000, 0x08010000, 0x08020000, 0x08040000, 0x08060000, 0x08080000, 0x080A0000, 0x080C0000, 0x080E0000, 0x08100000, }; static void flash_lock(void); static void flash_unlock(void); static KitResult flash_check_operation(int32_t timeout); static KitResult flash_check_operation(int32_t timeout) { KitResult res = kKitResult_Ok; while((FLASH->SR & FLASH_FLAG_BSY) == FLASH_FLAG_BSY) { if(timeout-- < 1) { return kKitResult_TimeOut; } } if((FLASH->SR & FLASH_FLAG_ERR) != 0) { res = kKitResult_Error; } return res; } static void flash_lock(void) { FLASH->CR |= CR_LOCK_Set; } static void flash_unlock(void) { FLASH->KEYR = FLASH_KEY1; FLASH->KEYR = FLASH_KEY2; FLASH->SR = (FLASH_FLAG_EOP| FLASH_FLAG_ERR); } int32_t flash_get_page_id(uint32_t start_addr) { int32_t i, res = -1; for(i = 0; i < 12; i++) { if(start_addr == page_start_addr[i]) { res = i; break; } } return res; } KitResult flash_read_u16(FlashItem *item, uint32_t addr,uint16_t *data) { KitResult res = kKitResult_Ok; KIT_ASSERT_PARAM((item != NULL) && (addr >= page_start_addr[item->start_page]) && ((addr + 2) <= page_start_addr[item->start_page + item->page_cnt])); if((item != NULL) && (addr >= page_start_addr[item->start_page]) && ((addr + 2) <= page_start_addr[item->start_page + item->page_cnt])) { *data = *((uint16_t *)addr); } else { res = kKitResult_ParamErr; } return res; } KitResult flash_read_u32(FlashItem *item, uint32_t addr, uint32_t *data) { KitResult res = kKitResult_Ok; KIT_ASSERT_PARAM((item != NULL) && (addr >= page_start_addr[item->start_page]) && ((addr + 4) <= page_start_addr[item->start_page + item->page_cnt])); if((item != NULL) && (addr >= page_start_addr[item->start_page]) && ((addr + 4) <= page_start_addr[item->start_page + item->page_cnt])) { *data = *((uint32_t *)addr); } else { res = kKitResult_ParamErr; } return res; } KitResult flash_write_u32(FlashItem *item, uint32_t addr, uint32_t value) { KitResult res; //OS_INIT_CRITICAL(); KIT_ASSERT_PARAM((item != NULL) && (addr >= page_start_addr[item->start_page]) && ((addr + 4) <= page_start_addr[item->start_page + item->page_cnt])); if((item != NULL) && (addr >= page_start_addr[item->start_page]) && ((addr + 4) <= page_start_addr[item->start_page + item->page_cnt])) { flash_unlock(); res = flash_check_operation(ProgramTimeout); if(res == kKitResult_Ok) { //OS_ENTER_CRITICAL(); //FLASH->ACR&=~(1<<10); //FLASH擦除期间,必须禁止数据缓存, FLASH->CR &= ~CR_PG_PSIZE; //清除PSIZE原来的设置 FLASH->CR |= 2 << 8; //设置为32bit宽,确保VCC=2.7~3.6V之间!! FLASH->CR |= CR_PG_Set; //编程使能 *(__IO uint32_t*)addr = value; res = flash_check_operation(ProgramTimeout); FLASH->CR &= ~CR_PG_Set; //FLASH->ACR|=1<<10; //OS_EXIT_CRITICAL(); } flash_lock(); } else { res = kKitResult_ParamErr; } return res; } KitResult flash_series_erase_page(FlashItem *item, uint32_t addr, uint32_t cnt) { int32_t start_page; uint32_t i; KitResult res = kKitResult_Error; //KIT_ASSERT_PARAM((item != NULL) && (addr >= item->start_addr) && ((addr + item->page_size * cnt) < item->end_addr)); //if((item != NULL) && (addr >= item->start_addr) && ((addr + item->page_size * cnt) < item->end_addr)) { start_page = flash_get_page_id(addr); if(start_page >= 0) { flash_unlock(); res = flash_check_operation(EraseTimeout); if(res == kKitResult_Ok) { FLASH->CR &= ~CR_PG_PSIZE; //清除PSIZE原来的设置 FLASH->CR |= 2 << 8; //设置为32bit宽,确保VCC=2.7~3.6V之间!! for (i = 0; i < cnt; i++) { FLASH->CR &= ~CR_PG_SNB; //清除原来的设置 FLASH->CR |= (start_page + i) << 3; //设置要擦除的扇区 FLASH->CR |= CR_PER_Set; FLASH->CR |= CR_SART; //开始擦除 flash_check_operation(EraseTimeout); FLASH->CR &= ~CR_PER_Set; } } flash_lock(); } } return res; } void flash_jump(uint32_t dest_addr, NoArgCall call) { uint32_t sp_addr = *(__IO uint32_t*)dest_addr; uint32_t app_addr = *(__IO uint32_t*)(dest_addr + 4); if ((sp_addr != 0xFFFFFFFF) && (app_addr != 0xFFFFFFFF) && ((sp_addr & 0xF0000000) == 0x20000000) && ((app_addr & 0x0F000000) == 0x08000000)) { __disable_irq(); call(); SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; __set_MSP(*(__IO uint32_t*) dest_addr); ((NoArgCall) (*(__IO uint32_t*)(dest_addr + 4)))(); } } uint32_t flash_get_page_size(FlashItem *item) { uint32_t res = 0xFFFFFFFF; KIT_ASSERT_PARAM(item != NULL); if(item != NULL) { if(item->start_page < 4) { res = 1024 * 16; } else if(item->start_page < 5) { res = 1024 * 64; } else { res = 1024 * 128; } } return res; } KitResult drv_flash_write_u32(uint32_t addr, uint32_t value) { KitResult res; flash_unlock(); res = flash_check_operation(ProgramTimeout); if(res == kKitResult_Ok) { FLASH->CR &= ~CR_PG_PSIZE; //清除PSIZE原来的设置 FLASH->CR |= 2 << 8; //设置为32bit宽,确保VCC=2.7~3.6V之间!! FLASH->CR |= CR_PG_Set; //编程使能 *(__IO uint32_t*)addr = value; res = flash_check_operation(ProgramTimeout); FLASH->CR &= ~CR_PG_Set; } flash_lock(); return res; } KitResult drv_flash_series_write_u32(uint32_t addr, uint8_t* buf, uint32_t len) { uint32_t i, data; KitResult res = kKitResult_ParamErr; if(((addr % 4) == 0) && (buf != NULL) && ((len % 4) == 0)) { len >>= 2; for(i = 0; i < len; i++) { data = ((uint32_t *)buf)[i]; res = drv_flash_write_u32(addr + (i << 2), data); if(res != kKitResult_Ok) break; if(((i + 1) % 300) == 0) drv_wdog_feed(); } } return res; } KitResult drv_flash_series_erase_page(uint32_t addr, uint32_t cnt) { int32_t i, start_page; KitResult res = kKitResult_Error; start_page = flash_get_page_id(addr); if(start_page >= 0) { flash_unlock(); res = flash_check_operation(EraseTimeout); if(res == kKitResult_Ok) { FLASH->CR &= ~CR_PG_PSIZE; //清除PSIZE原来的设置 FLASH->CR |= 2 << 8; //设置为32bit宽,确保VCC=2.7~3.6V之间!! for (i = 0; i < cnt; i++) { FLASH->CR &= ~CR_PG_SNB; //清除原来的设置 FLASH->CR |= (start_page + i) << 3; //设置要擦除的扇区 FLASH->CR |= CR_PER_Set; FLASH->CR |= CR_SART; //开始擦除 flash_check_operation(EraseTimeout); FLASH->CR &= ~CR_PER_Set; } } flash_lock(); } return res; }