实验4- FlashRom和SD卡

一.Flash地址空间的数据读取

1、Flash地址空间的基本原理
不同型号的 STM32,其 FLASH 容量也有所不同,最小的只有 16K 字节,最大的则达到了1024K 字节。市面上 STM32F1 开发板使用的芯片是 STM32F103系列,其 FLASH 容量一般为 512K 字节,属于大容量芯片; Flash的编程原理都是只能将1写为0,而不能将0写为1,所以在进行Flash编程前,必须将对应的块擦除,即将该块的每一位都变为1,块内所有字节变为0xFF。
STM32F1 的闪存(Flash)模块:主存储器、信息块、闪存存储器接口寄存器,在执行闪存写操作时,任何对闪存的读操作都会锁住总线,在写操作完成后读操作才能正确地进行;既在进行写或擦除操作时,不能进行代码或数据的读取操作。

2、使用工具
STM32F103C8T6、STlink、Keil、STM32CubeMX
3.工程配置
3.1具体要求

lash地址空间的数据读取。stm32f103c8t6只有20KB 内存(RAM)供程序代码和数组变量存放,因此,针对内部Flash的总计64KB存储空间(地址从0x08000000开始),运行一次写入8KB数据,总计复位运行代码8次,将64KB数据写入Flash,并验证写入数据的正确性和读写速率。此外,继续往后续地址写入数据,检验stm32f103c8t6 实际FlashROM是否超过64KB。

3.2CubeMx建立工程

首先打开CubeMx,点击左上角的File文件选择“New Project”,创建工程,在弹出的界面中,下拉列表输入芯片名称“STM32F103C8T6”,右下角选中后,点击“Start Project,
在这里插入图片描述然后配置“.sys”,下拉debug模式 ,选中"Serial Wire"Timebase Source选择“SysTick”,
在这里插入图片描述
接着配置“.RCC”,HSE选中"Crystal/Ceramic Resonator"项,LSE选择Disable,
在这里插入图片描述系统时钟树配置,
在这里插入图片描述
配置GPIO口,对应外设c8t6本身设计好的PC13 LED灯,在这里插入图片描述
中断配置(保持默认),在这里插入图片描述
设置堆栈大小为4K或2K,
在这里插入图片描述
接着设置Project Manager,
在这里插入图片描述
最后设置“Code Generator”,勾选图示内容,再点击右上角"GENERATE CODE",生成文件,再用keil打开工程即可。在这里插入图片描述
3.3添加相关代码

先在工程文件中创建lash.c和flash.h,然后在keil中同样创立两个新文件,flash.c和flash.h,
在这里插入图片描述
接着添加flash.c和flash.h的相关代码
flash.c:

/*
 * flash.c
 *
 * Created: 2018-01-29
 * Author: zhanglifu
 */
 
/*********************************************************************/
//                        Í·Îļþ
/*********************************************************************/
#include "flash.h"
 
 
// ²»¼ì²éµÄдÈë
// WriteAddr:ÆðʼµØÖ·
// pBuffer:  Êý¾ÝÖ¸Õë
// NumToWrite:×Ö½ÚÊýÊý
void FlashWriteNoCheck( uint32_t WriteAddr,uint8_t *pBuffer,uint16_t NumToWrite )
{
    uint16_t i;
 
    for( i=0; i<NumToWrite; i+=4 )
    {
        while( HAL_OK != HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, WriteAddr+i,*(uint32_t *)(pBuffer+i) ) );
    }
 
}
 
extern void FLASH_PageErase(uint32_t PageAddress);
void FlashWriteBuff( const uint32_t destination_address, uint8_t *const buffer,uint32_t length )
{
    uint16_t i;
    uint8_t FlashBuff[FMC_SECTOR_SIZE];
    uint32_t StartAddress = destination_address - destination_address%FMC_SECTOR_SIZE;
    uint16_t Offset = destination_address - StartAddress;
    uint8_t *pBuf = buffer;
    uint32_t remaindNum = length;
 
    HAL_StatusTypeDef status = HAL_ERROR;
 
    // µØÖ·¼ì²é
    if( (destination_address < FMC_FLASH_BASE) || ( destination_address + length >= FMC_FLASH_END) || (length <= 0) )
        return;
 
    HAL_FLASH_Unlock();	// ½âËø
    do
    {
        // ¶Á³öÒ»Ò³Êý¾Ý
        for(i=0; i < FMC_SECTOR_SIZE; i += 4 )
            *(uint32_t *)(FlashBuff+i) = *(uint32_t *)(StartAddress+i);
 
        // ÐÞ¸ÄÒª¸ÄÈëµÄÊý¾Ý
        for ( i=0; (i+Offset)<FMC_SECTOR_SIZE && i< remaindNum; i++ )
            *(FlashBuff+Offset+i) = *(pBuf+i);
 
 
        // ²Á³ýÒ»ROWÊý¾Ý
        FLASH_PageErase( StartAddress );
 
        // HAL¿â FLASH_PageEraseÓÐBUFF,Òª¼ÓÉÏÏÂÃæÈýÐдúÂë
        while( status != HAL_OK )
            status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
        CLEAR_BIT(FLASH->CR, FLASH_CR_PER);
 
        // дÈëÊý¾Ý
        FlashWriteNoCheck( StartAddress,FlashBuff,FMC_SECTOR_SIZE );
 
        // ΪÏÂÒ»Ò³×ö×¼±¸
        StartAddress +=  FMC_SECTOR_SIZE;
        remaindNum -= i;
        pBuf += i;
        Offset = 0;
 
    } while( remaindNum > 0 );
 
    HAL_FLASH_Lock();  // ÉÏËø
		
}
 
 
 
// ´ÓFLASHÖжÁÖ¸¶¨³¤¶ÈÊý¾Ý
void FlashReadBuff(const uint32_t source_address,uint8_t *const buffer,uint16_t length)
{
    uint16_t i;
    uint8_t Offset = 0;
    uint32_t StartAddress = source_address;
    uint16_t data;
 
    // µØÖ·¼ì²â
    if( source_address + length > FMC_FLASH_END ) return;
 
    // Èç¹ûûÓжÔ16Æë
    if( source_address & 1 )
    {
        Offset = 1;
        StartAddress = source_address-1;
    }
 
    // flashµÄ²Ù×÷ÒªÇó16¶ÔÆë ×îС¶Áд²Ù×÷16¸ö±ÈÌØ
    if ( Offset )
    {
        data = *(uint16_t *)(StartAddress);
        buffer[0] = data >> 8;
        StartAddress += 2;
    }
 
    for ( i = 0; i < (length-Offset); i += 2)
    {
        data = *(uint16_t *)(StartAddress+i);
        buffer[i+Offset] = (data & 0xFF);
        if ( (i+Offset) < (length - 1) )
            buffer[i + Offset + 1] = (data >> 8);
    }
 
}
 

flash.h:

/*
 * flash.h
 *
 * Created: 2016-04-22
 * Author: zhanglifu
 */
#ifndef _flash_H_
#define _flash_H_
 
 
#include "stm32f1xx_hal.h"
 
 
/*********************************************************************/
//                        ±äÁ¿¶¨Òå
/*********************************************************************/
//-- ÓÃ;»®·Ö
// 0x0800FC00-0x0800FFFF -- ʹÓÃ×îºó4k ¸ö×Ö½ÚÓÃÀ´´æ·Åµç»úÐÅÏ¢
#define FMC_FLASH_BASE      0x08000000 	// FLASHµÄÆðʼµØÖ·
#define APP_MAX_SIZE        0x00010000  // 
 
 
#define FMC_FLASH_END        0x08010000  // FLASHµÄ½áÊøµØÖ· 256
#define DEVICE_INFO_ADDRESS  0x0800C000  //£¨STM32_FLASH_END - DEVICE_INFO_SIZE£©   // É豸ÐÅÏ¢ÆðʼµØÖ·
#define DEVICE_LOG_ADDRESS   0x0800E000  //£¨STM32_FLASH_END - 2*DEVICE_INFO_SIZE£© // É豸ÈÕÖ¾ÆðʼµØÖ·
 
 
 
#define FMC_FLASH_SIZE 64			          // ¶¨ÒåFlash´óС£¬µ¥Î»KB
 
 
#if FMC_FLASH_SIZE < 256
#define FMC_SECTOR_SIZE 1024            // ×Ö½Ú
#define MOD_SECTOR_SIZE 0X3FF
#define PAGE_COUNT_BY16 512
#else
#define FMC_SECTOR_SIZE	2048
#define MOD_SECTOR_SIZE 0X7FF
#define PAGE_COUNT_BY16 1024
#endif
 
 
 
 
 
/*********************************************************************/
//                        º¯ÊýÉùÃ÷
/*********************************************************************/
void FlashWriteBuff( const uint32_t destination_address, uint8_t *const buffer,uint32_t length );
void FlashReadBuff(const uint32_t source_address,uint8_t *const buffer,uint16_t length);
 
 
 
 
#endif

在main.c文件中添加部分代码,
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
编译无误,使用STlink下载即可。
dd2f34393d84b4.png)

4.程序调试
点击View->memory windows->memory 1打开内存观察窗口,并在地址栏中输入:0x800c000,观察将要修改的flash区间区容。
在这里插入图片描述

View->Watch windows->Watch 1打开一个变量观察窗口,将变量FlashWBuff 和 FlashRBuff加入到 Watch 1 观察窗口,View->Periodic Windows Update开启变量自动更新在这里插入图片描述点击全速运行,同时在Memory 1窗口中可以看到在FLASH地址0x0800C000区成功写入对应内容,
在这里插入图片描述

二.总结

本次实验聚焦于 stm32f103c8t6 芯片的 Flash 地址空间数据读取相关操作。鉴于该芯片仅有 20KB 的 RAM 用于存放程序代码与数组变量,于是把目光投向了内部 Flash 的 64KB 存储空间(起始地址为 0x08000000)。实验过程采取分批次写入的策略,每次写入 8KB 数据,历经 8 次复位运行代码,达成 64KB 数据完整写入 Flash 的目标。在此之后,着重验证写入数据的准确性以及读写速率,以此衡量数据存储的可靠性与读写性能。不仅如此,实验还进一步尝试往后续地址写入数据,意图探究该型号芯片实际 FlashROM 容量是否突破标称的 64KB ,全面挖掘芯片的存储潜力。
心得
整个实验下来,感受颇为深刻。一开始面对有限的 RAM 和 Flash 存储空间规划,着实费了一番脑筋,这使我对芯片的存储架构有了更前置性的思考,意识到资源受限下合理分配的重要性。在执行 8KB 数据多次写入 Flash 的操作时,每一次复位、写入的循环,都像是在和芯片的底层逻辑对话,我开始理解复杂的写入流程背后是为了确保数据稳定存储。
验证数据正确性环节,看着读出的数据与写入的完美匹配,满心都是成就感,也更清楚严谨测试对于保障数据完整性的意义。而探究读写速率,让我察觉到性能优化的空间,思考如何在现有硬件条件下减少等待时间、提升效率。尝试向后续地址写入数据充满未知与期待,虽然最终结果可能未超出 64KB,但这个探索过程加深了我对芯片物理极限的认知,激发了钻研硬件底层的热情,往后面对类似存储相关项目,相信这次积累的经验能让我更加游刃有余。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值