123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297 |
- #include "st_sys.h"
- #include "st_flash.h"
- #include "hardware_delay.h"
- typedef struct
- {
- uint32_t addr;
- uint32_t size;
- }
- st_flash_page_info;
- /**
- * FLASH页分块表
- *
- * @author lxz (121319 18:16:08)
- */
- static const st_flash_page_info page_infos[] = {
- { ST_FLASH_SECTOR_0, 24 * 1024},
- { ST_FLASH_SECTOR_2, 16 * 1024},
- { ST_FLASH_SECTOR_3, 4 * 1024},
- { ST_FLASH_SECTOR_5, 212 * 1024 }
- };
- /**
- * flash 操作解锁
- *
- * @author lxz (2019/5/30/鍛ㄥ洓)
- *
- * @param void
- */
- void st_flash_unlock(void) {
- if (FLASH->CR & (1 << 7)) {
- FLASH->KEYR = FLASH_KEY1;
- FLASH->KEYR = FLASH_KEY2;
- }
- //清除错误标志位
- FLASH->SR = FLASH_SR_PGERR |FLASH_SR_WRPRTERR;
- }
- /**
- * flash操作 上锁
- *
- * @author lxz (2019/5/30/鍛ㄥ洓)
- *
- * @param void
- */
- void st_flash_lock(void) {
- FLASH->CR |= ((uint32_t)1) << 7; //Bank1,涓婇攣
- }
- /**
- * 获取flash状态
- *
- * @author LXZ (121819)
- *
- * @return int
- */
- int st_flash_error_no(void) {
- int res = 0;
- res = FLASH->SR;
- if (res & (1 << 0)) return 1; //忙
- else if (res & (1 << 2)) return 2; //页面错误
- else if (res & (1 << 4)) return 3; //写保护
- return 0; //没有任何状态/操作完成
- }
- int flash_last_wait_time = 0;
- /**
- * 等待操作完成
- *
- * @author lxz (2019/5/30/鍛ㄥ洓)
- *
- * @param bankx
- * @param time 等待时间
- */
- int st_flash_wait_done(int time) {
- int res = 0;
- do {
- res = st_flash_error_no();
- if (res != 1) break; //非忙,无需等待了,直接退出.
- hw_delay_us(1);
- time--;
- }while (time);
- if (time == 0) res = 0xff; //TIMEOUT
- flash_last_wait_time = time;
- return res;
- }
- /**
- *擦除扇区
- *
- * @author lxz (2019/5/30/鍛ㄥ洓)
- *
- * @param sector_no
- *
- * @return int
- */
- int st_flash_erase_secotr(uint8_t sector_no) {
- int res = 0;
- int number = 0;
- int blockNumber = page_infos[sector_no].size;
- uint32_t addr = page_infos[sector_no].addr;
- int page_size = 1024;
- //FLASH->ACR &= ~(1 << 4);
- res = st_flash_wait_done(20000); //绛夊緟涓婃鎿嶄綔缁撴潫,鏈€澶?s
- if (__ST_FLASH_SIZE >= 0x100) {
- page_size = 2048;
- }
- blockNumber /= page_size;
- while (res == 0 && number < blockNumber) {
- //FLASH->CR&=~(3<<8); //清除PSIZE原来的设置
- //FLASH->CR|=2<<8; //设置为32bit宽,确保VCC=2.7~3.6V之间!!
- //FLASH->CR&=~(0X1F<<3);//清除原来的设置
- //FLASH->CR|=sector_no<<3;//设置要擦除的扇区
- FLASH->CR |= 1 << 1; //扇区擦除
- FLASH->AR = addr;
- FLASH->CR |= 1 << 6; //开始擦除
- res = st_flash_wait_done(20000); //等待操作结束,最大2s
- if (res != 1) { //非忙
- FLASH->CR &= ~(1 << 1); //清除扇区擦除标志.
- }
- number++;
- addr += page_size;
- }
- //FLASH->ACR |= (1 << 4);
- return res;
- }
- /**
- * 往指定地址写入一个字,地址必须保证字对齐
- *
- * @author lxz (2019/5/30/鍛ㄥ洓)
- *
- * @param faddr
- * @param pdata
- *
- * @return int
- */
- int st_flash_write_flash_word(uint32_t faddr, uint32_t pdata) {
- u8 res;
- res = st_flash_wait_done(0XFF);
- if (res == 0) { //OK
- FLASH->CR |= 1 << 0;
- *(vu16 *)faddr = pdata;
- res = st_flash_wait_done(0XFF);
- if (res == 0) {
- FLASH->CR &= ~(1 << 0);
- }
- }
- res = st_flash_wait_done(0XFF);
- faddr += 2;
- pdata >>= 16;
- if (res == 0) {
- FLASH->CR |= 1 << 0;
- *(vu16 *)faddr = pdata;
- res = st_flash_wait_done(0XFF);
- if (res == 0) {
- FLASH->CR &= ~(1 << 0);
- }
- }
- return res;
- }
- int st_flash_write_half_word(uint32_t faddr, uint16_t pdata) {
- u8 res;
- res = st_flash_wait_done(0XFF);
- if (res == 0) { //OK
- FLASH->CR |= 1 << 0;
- *(vu16 *)faddr = pdata;
- res = st_flash_wait_done(0XFF);
- if (res == 0) {
- FLASH->CR &= ~(1 << 0);
- }
- }
- return res;
- }
- /**
- * 读取指定地址一个32位数据
- *
- * @author LXZ (121819)
- *
- * @param faddr
- *
- * @return uint32_t
- */
- uint32_t st_flash_read_word(uint32_t faddr) {
- return *(vu32 *)faddr;
- }
- /**
- * 閫氳繃鍦板潃鑾峰彇鎵€鍦ㄧ殑鎵囧尯鍙?
- *
- * @author lxz (2019/5/30/鍛ㄥ洓)
- *
- * @param addr
- *
- * @return uint8_t
- */
- uint8_t st_flash_addr_to_sector_no(uint32_t addr) {
- int i = 0;
- while ((page_infos[i].addr + page_infos[i].size) <= addr &&
- i < (sizeof(page_infos) / sizeof(st_flash_page_info))) { //计算块大小是否已经包含了地址
- i++;
- }
- return i;
- }
- /**
- * 向指定地址写入32位数据
- *
- * @author LXZ (121819)
- *
- * @param addr
- * @param buffer
- * @param length
- *
- * @return int
- */
- int st_flash_write(uint32_t addr, uint32_t *buffer, uint32_t length) {
- int status = 0;
- uint32_t addrx = 0;
- uint32_t endaddr = 0;
- if (addr < STM32_FLASH_BASE || addr % 4) return 1; //非法地址
- st_flash_unlock(); //解锁
- //FLASH->ACR &= ~(1 << 10); //FLASH擦除期间,必须禁止数据缓存!!!搞了我两晚上才发现这个问题!
- addrx = addr; //写入的起始地址
- endaddr = addr + length * 4; //写入的结束地址
- if (addrx < 0X1FFF0000) { //只有主存储区,才需要执行擦除操作!!
- while (addrx < endaddr) { //扫清一切障碍.(对非FFFFFFFF的地方,先擦除)
- if (st_flash_read_word(addrx) != 0XFFFFFFFF) { //有非0XFFFFFFFF的地方,要擦除这个扇区
- status = st_flash_erase_secotr(st_flash_addr_to_sector_no(addrx));
- if (status) break; //发生错误了
- } else addrx += 4;
- }
- }
- if (status == 0) {
- uint16_t * dat = (uint16_t *)buffer;
- while (addr < endaddr) {
- if (st_flash_write_half_word(addr, *dat)) { //写入数据
- break; //写入异常
- }
- //sw_timer_now(&timer);
- addr += 2;
- dat++;
- }
- /*
- while (addr < endaddr) { //写数据
- //sw_timer_now(&timer2);
- if (st_flash_write_flash_word(addr, *buffer)) { //写入数据
- break; //写入异常
- }
- //sw_timer_now(&timer);
- addr += 4;
- buffer++;
- }
- */
- } else {
- while (1);
- }
- //FLASH->ACR |= 1 << 10; //FLASH擦除结束,开启数据fetch
- st_flash_lock(); //上锁
- return 0;
- }
- /**
- * 读取指定长度的32位数据
- *
- * @author LXZ (121819)
- *
- * @param addr
- * @param buffer
- * @param length
- */
- void st_flash_read(uint32_t addr, uint32_t *buffer, uint32_t length) {
- int i;
- for (i = 0; i < length; i++) {
- buffer[i] = st_flash_read_word(addr);
- addr += 4;
- }
- }
|