组员:吴迪&王柳杨&金虎&陈武荣&谭金柏 Flash reply 电子科技大学 Flash 解析 第七组 组长:黄其柏 组员:吴迪&王柳杨&金虎&陈武荣&谭金柏 电子科技大学
目录 Contents Flash reply 1 Flash 简介&设备特性&工作原理 2 函数功能介绍&代码剖析 3 相关寄存器简介 4 电子科技大学 1 Flash 简介&设备特性&工作原理 目录 Contents 2 函数功能介绍&代码剖析 3 相关寄存器简介 电子科技大学 4 感谢
Flash reply Flash 简介 FLASH 存储器: 电子科技大学 Flash 简介 FLASH 存储器: FLASH 存储器又称为闪存,它也是可重复擦写的存储器,部分书籍会把 FLASH 存储器称为 FLASH ROM,但它的容量一般比 EEPROM 大得多,且在擦除时,一般以多个字节为单位。 根据存储单元电路的不同,FLASH 存储器又分为 NOR FLASH 和 NAND FLASH。 电子科技大学
Flash reply 电子科技大学 Flash 设备特性 电子科技大学
Flash reply Flash 工作原理 电子科技大学 支持 XIP(应用程序可以直接在flash闪存内运行,不必再把代码读到系统RAM中。),才能直接运行代码,SD 卡,硬盘,U 盘其实都是 NAND FLASH。
Flash reply stm_flash.h: 电子科技大学 #define STM32_FLASH_KEY1 0x45670123 #define STM32_FLASH_KEY2 0xCDEF89AB #define STM32_FLASH_SR_BSY (1 << 16) #define STM32_FLASH_CR_PG (1 << 0) #define STM32_FLASH_CR_SER (1 << 1) #define STM32_FLASH_CR_STRT (1 << 16) #define STM32_FLASH_CR_LOCK (1 << 31) #define STM32_FLASH_CR_SNB_OFFSET 3 #define STM32_FLASH_CR_SNB_MASK (15 << STM32_FLASH_CR_SNB_OFFSET) /* Flash ACR: Access control register */ #define FLASH_ACR_WS(n) n #define FLASH_ACR_PRFTEN (1 << 8) #define FLASH_ACR_ICEN (1 << 9) #define FLASH_ACR_DCEN (1 << 10) struct stm32_flash_regs { u32 acr; u32 key; u32 optkeyr; u32 sr; u32 cr; u32 optcr; u32 optcr1; }; 电子科技大学
Flash reply stm_flash.c: //头文件 #include <common.h> 电子科技大学 stm_flash.c: //头文件 #include <common.h> #include <asm/io.h> #include <asm/arch/stm32.h> #include "stm32_flash.h“ //flash信息结构体 flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; //flash基地址 #define STM32_FLASH ((struct stm32_flash_regs *)FLASH_CNTL_BASE) 电子科技大学
Flash reply 电子科技大学 //配置 Flash等待周期 、预取指令、指令缓存和数据缓存 void stm32_flash_latency_cfg(int latency) //加解锁 static void stm32_flash_lock(u8 lock) //flash初始化 unsigned long flash_init(void) //flash打印信息 void flash_print_info(flash_info_t *info) //flash擦除扇区 int flash_erase(flash_info_t *info, int first, int last) 电子科技大学 //flash写入 int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
Flash reply 源码解析: flash基地址在stm32中:0x4002 3C00 挂在高速总线AHB1上 //flash基地址 电子科技大学 源码解析: //flash基地址 #define STM32_FLASH ((struct stm32_flash_regs *)FLASH_CNTL_BASE) 采用相对寻址的方式: #define FLASH_CNTL_BASE (AHB1_PERIPH_BASE + 0x3C00) #define AHB1_PERIPH_BASE (PERIPH_BASE + 0x00020000) #define PERIPH_BASE 0x40000000UL 电子科技大学 flash基地址在stm32中:0x4002 3C00 挂在高速总线AHB1上
Flash reply 知识扩展: stm32总线基地址: APB1 0x4000 0000 0x0(相对总线基地址偏移量) 电子科技大学 stm32总线基地址: APB1 0x4000 0000 0x0(相对总线基地址偏移量) APB2 0x4001 0000 0x0001 0000 AHB1 0x4002 0000 0x0002 0000 AHB2 0x5000 0000 0x1000 0000 AHB3 0x6000 0000 不在片上外设范围内 总线的基址:APB1 0x4000 0000 知识扩展: AHB系统总线(高速):主要用于高性能模块之间的连接,如CPU、DMA和DSP等。 APB外围总线(低速)APB主要用于低带宽的周边外设之间的连接,如UART等。 电子科技大学
Flash reply 源码解析: //配置 Flash等待周期 、预取指令、指令缓存和数据缓存 电子科技大学 源码解析: //配置 Flash等待周期 、预取指令、指令缓存和数据缓存 void stm32_flash_latency_cfg(int latency) { writel(FLASH_ACR_WS(latency) | FLASH_ACR_PRFTEN | FLASH_ACR_ICEN | FLASH_ACR_DCEN, &STM32_FLASH->acr); } 内联函数定义:static inline void writel(u32 val, void *addr) 内联函数减少了对栈的进出时间的开销,却扩大了主存的空间来容纳本来在栈里的函数。 电子科技大学 *(u32 *)addr = val;//将对应的值写入地址
Flash reply 源码解析: FLASH_ACR_WS(latency) 电子科技大学 源码解析: FLASH_ACR_WS(latency) 为了准确读取 Flash 数据,必须根据 CPU 时钟 (HCLK) 频率和器件电源电压在 Flash 存取控制寄存器 (FLASH_ACR) 中正确地编程等待周期数 (LATENCY)。 FLASH时序延迟几个周期,等待总线同步操作。 推荐按照单片机系统运行频率, 0~24MHz时,取Latency=0; 24~48MHz时,取Latency=1; 48~72MHz时,取Latency=2; 电子科技大学 FLASH_ACR_PRFTEN 预取指令 FLASH_ACR_ICEN 指令缓存 FLASH_ACR_DCEN 数据缓存
Flash reply 电子科技大学 电子科技大学
Flash reply 电子科技大学 源码解析: static void stm32_flash_lock(u8 lock) { if (lock) { //加锁,将STM32_FLASH->cr的最高位置1 setbits_le32(&STM32_FLASH->cr, STM32_FLASH_CR_LOCK); } else { //解锁 writel(STM32_FLASH_KEY1, &STM32_FLASH->key); writel(STM32_FLASH_KEY2, &STM32_FLASH->key); } #define setbits_le32(addr, set) setbits(le32, addr, set) #define setbits(type, addr, set) write_##type((addr), read_##type(addr) | (set)) #define STM32_FLASH_CR_LOCK (1 << 31) 电子科技大学 解锁 (1) 往 Flash 密钥寄存器 FLASH_KEYR 中写入 KEY1 = 0x45670123 (2) 再往 Flash 密钥寄存器 FLASH_KEYR 中写入 KEY2 = 0xCDEF89AB
源码解析: //flash初始化 电子科技大学 unsigned long flash_init(void) { unsigned long total_size = 0; u8 i, j; for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) { flash_info[i].flash_id = FLASH_STM32;//使能stm32的flash flash_info[i].sector_count = CONFIG_SYS_MAX_FLASH_SECT;//最大分配扇区数量 flash_info[i].start[0] = CONFIG_SYS_FLASH_BASE + (i << 20);//虚拟的扇区地址 flash_info[i].size = sect_sz_kb[0];//每个扇区的大小空间 for (j = 1; j < CONFIG_SYS_MAX_FLASH_SECT; j++) { /*下一个扇区的起始地址是上一个的起始地址+上一个扇区的大小*/ flash_info[i].start[j] = flash_info[i].start[j - 1] + (sect_sz_kb[j - 1]); //累加,一个flash中每个扇区加起来的总大小 flash_info[i].size += sect_sz_kb[j]; } total_size += flash_info[i].size;//累加,多个flash总大小空间 return total_size; //返回总大小空间 电子科技大学
i<<20:表示每个flash最大分配空间1024KB CONFIG_SYS_MAX_FLASH_SECT:最大被分配扇区数量 flash_info[i].start[0] = CONFIG_SYS_FLASH_BASE + (i << 20);//虚拟的扇区起始地址0xbfc00000, i<<20:表示每个flash最大分配空间1024KB CONFIG_SYS_MAX_FLASH_SECT:最大被分配扇区数量 flash_info[i].size:每个扇区的大小 for (j = 1; j < CONFIG_SYS_MAX_FLASH_SECT; j++) { /*下一个扇区的起始地址是上一个的起始地址+上一个扇 区的大小*/ flash_info[i].start[j] = flash_info[i].start[j - 1] + (sect_sz_kb[j - 1]); //每个扇区加起来的总大小 flash_info[i].size += sect_sz_kb[j]; } 电子科技大学
总共1024KB,被分成8个扇区 0~3 32KB 4 128KB 5~7 256KB Flash的扇区的大小排列(Byte): static const u32 sect_sz_kb[CONFIG_SYS_MAX_FLASH_SECT] = { [0 ... 3] = 32 * 1024, [4] = 128 * 1024, [5 ... 7] = 256 * 1024 }; 总共1024KB,被分成8个扇区 0~3 32KB 4 128KB 5~7 256KB 电子科技大学
这部分 没什么好讲的 //flash打印信息 电子科技大学 void flash_print_info(flash_info_t *info) { int i; if (info->flash_id == FLASH_UNKNOWN) { printf("missing or unknown FLASH type\n"); return; } else if (info->flash_id == FLASH_STM32) { printf("stm32 Embedded Flash\n"); } printf(" Size: %ld MB in %d Sectors\n", info->size >> 20, info->sector_count); printf(" Sector Start Addresses:"); for (i = 0; i < info->sector_count; ++i) { if ((i % 5) == 0) printf("\n "); printf(" %08lX%s", info->start[i], info->protect[i] ? " (RO)" : " "); printf("\n"); 这部分 没什么好讲的 电子科技大学
//flash擦除扇区 int flash_erase(flash_info_t *info, int first, int last) { u8 bank = 0xFF; int i; //找到要擦除的flash for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) { if (info == &flash_info[i]) { bank = i; break; } if (bank == 0xFF)//不存在 return -1; //解锁flash stm32_flash_lock(0); for (i = first; i <= last; i++) { //检查 FLASH_SR 状态寄存器中的 BSY 位,以确认当前未执行任何 Flash 操作 while (readl(&STM32_FLASH->sr) & STM32_FLASH_SR_BSY); /*在写入新的扇区之前,先清除旧的扇区*/ clrbits_le32(&STM32_FLASH->cr, STM32_FLASH_CR_SNB_MASK); 电子科技大学
电子科技大学 if (bank == 0) { //设置操作的扇区编号0 setbits_le32(&STM32_FLASH->cr, (i << STM32_FLASH_CR_SNB_OFFSET)); } else if (bank == 1) { //设置扇区编号1 setbits_le32(&STM32_FLASH->cr,((0x10 | i) << STM32_FLASH_CR_SNB_OFFSET)); } else { stm32_flash_lock(1);//加锁,返回异常 return -1; } //在 FLASH_CR 寄存器中,将 SER 位置 1,激活扇区擦除 setbits_le32(&STM32_FLASH->cr, STM32_FLASH_CR_SER); //将 FLASH_CR 寄存器中的 STRT 位置 1,该位置 1 后可触发擦除操作。 //该位只能通过软件置 1,并在 BSY 位清零后随之清零。 setbits_le32(&STM32_FLASH->cr, STM32_FLASH_CR_STRT); while (readl(&STM32_FLASH->sr) & STM32_FLASH_SR_BSY);//等待 BSY 位清零 //在 FLASH_CR 寄存器中,将 SER 位置 0 clrbits_le32(&STM32_FLASH->cr, STM32_FLASH_CR_SER); stm32_flash_lock(1);//擦除完加锁 return 0; 电子科技大学
知识扩展: 扇区擦除 电子科技大学 扇区擦除的具体步骤如下: 1.检查 FLASH_SR 寄存器中的 BSY 位,以确认当前未执行任何 Flash 操作 2. 在 FLASH_CR 寄存器中,将 SER 位置 1,并从主存储块的 12 个 (STM32F405xx/07xx 和 STM32F415xx/17xx) 或 24 个 (STM32F42xxx 和 STM32F43xxx) 扇区中选择要擦除的扇区 (SNB) 3. 将 FLASH_CR 寄存器中的 STRT 位置 1 4. 等待 BSY 位清零 批量擦除,建议采用以下步骤: 2. 将 FLASH_CR 寄存器中的 MER 位置 1(STM32F405xx/07xx 和 STM32F415xx/17xx 器件) 3. 将 FLASH_CR 寄存器中的 MER 和 MER1 位置 1(STM32F42xxx 和 STM32F43xxx 器件) 4. 将 FLASH_CR 寄存器中的 STRT 位置 1 5. 等待 BSY 位清零批量擦除 电子科技大学
int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt) { ulong i; /*检查 FLASH_SR 状态寄存器中的 BSY 位,以确认当前未执行 任何 Flash 操作*/ while (readl(&STM32_FLASH->sr) & STM32_FLASH_SR_BSY); //解锁 stm32_flash_lock(0); //将cr寄存器的PG位置一,激活 Flash 编程 setbits_le32(&STM32_FLASH->cr, STM32_FLASH_CR_PG); 电子科技大学
for (i = 0; i < cnt; i++) { //写入数据 *(uchar *)(addr + i) = src[i]; //把当前CPU寄存器中的被修改过的数值存入内存 mb(); //等待 BSY 位清零 while (readl(&STM32_FLASH->sr) & STM32_FLASH_SR_BSY); } //将cr寄存器的PG位置一,关闭激活 Flash 编程 clrbits_le32(&STM32_FLASH->cr, STM32_FLASH_CR_PG); stm32_flash_lock(1);//加锁 return 0; 电子科技大学
mb(); #define mb() asm volatile("dmb 3\n" : : : "memory") 告诉编辑器,内存已经被修改,编辑器就会在这段指令之前,插入必要的指令将前面因为优化Cache 到寄存器中的变量值先写回内存,如果以后又要使用这些变量再重新读取。 DMB 指令保证: 仅当所有在它前面的存储器访问操作 都执行完毕后,才提交在它后面的存储器访问操作。 电子科技大学
Flash reply 电子科技大学 Associate Register Here 相关寄存器介绍
电子科技大学
电子科技大学
电子科技大学
电子科技大学
电子科技大学
电子科技大学
电子科技大学
电子科技大学
电子科技大学
电子科技大学
电子科技大学
电子科技大学
Thanks For Watching! Flash reply 电子科技大学 版权声明:300套精品模板商业授权,请联系【锐旗设计】:https://9ppt.taobao.com,专业PPT老师为你解决所有PPT问题!