基于国民技术N32G435的FLASH读写测试

news2024/11/22 13:20:57

一、测试工具:

1.国民技术N32G43XCL-STB开发板----主控为N32G435CB
在这里插入图片描述
2.创芯工坊PW200加密离线烧录器
在这里插入图片描述
3.PowerWriter上位机,配合PW200查看FLASH数据。
在这里插入图片描述

4.keil5

二、测试背景

现在很多的应用中都需要保存离线数据,例如一些传感器的校正数据,每一块成片中的数据可能都不相同,不能每一次掉电后重启都重新进行一次校准,那样用户的体验感会非常不好,此时就需要掉电不丢失数据。一般的方式是在MCU外置一颗EEPROM芯片,通过MCU的I2C与其通信(例如AT24C02),此方法好处在于不占用片内FLASH,而且外置EEPROM大小灵活,对于大数据的掉电储存较为合适,毕竟MCU的FLASH容量有限,如果项目过大,可能没有太多的空闲FLASH预留给用户储存数据。但是缺点也很明显,占用PCB的版面,对于小尺寸的PCB很不友好,工作时也增加功耗,同时目前的EEPROM期间也存在溢价严重的问题,增加产品的成本。如果是少量的数据保存,优先还是片内FLASH。

FLASH操作注意事项:

1.每一款单片机的FLASH的大小不尽相同,在操作FLASH之前一定要根据手册确定手里的单片的FLASH的大小,超出FLASH容量的写操作是不被允许的,也无法成功完成数据写入。
2.计算好程序的内存,程序也是保存在FLASH中,如果没有计算好程序的大小,将写FLASH写入程序占用的内存中,会导致程序奔溃。
3.写数据之前必须先对页进行擦除,因为FLASH不能写1,只能写0,所以写之前要通过擦除操作将FLASH页中的数据全部恢复为FF,才能进行写操作,如果该FLASH中存在需要的数据,必须要先将数据读出来存在缓存区,再将页擦除,再进行写数据。
4.数据不超过一页,可连续写入。
5.注意FLASH的操作单位,每次最少写4个字节,可通过手册查询页的大小,因为一般采用的是整页的擦除和写入,不可随意擦写。
6.操作FLASH时会占用总线,会打断你的中断操作,且写FLASH时间一般较长,所以在操作FLASH时要保证单片机预留出足够的时间。

针对上述的注意事项,这里以N32G435CB为例,进行一次FLASH的操作流程讲解(此过程对其他单片机同样适用):

1.根据我们的单片机型号,从手册中可查询到片内FLASH为128K。

在这里插入图片描述

2.根据储存器映射图,可以了解到FLASH的地址是0x08000000-0x0801FFFF。那我们可操作的FLASH地址只能限制在该范围内,但是代码本身也是要占用FLASH空间的,那我们就需要去计算代码所占空间。

在这里插入图片描述

3. 查询代码所占空间可以找到工程中的.bin文件,看他的大小。

在这里插入图片描述

上图的.bin文件的大小为9KB,根据手册查询FLASH页面大小是2K,那么就需要5页,对应到FLASH的地址为0x08000000-0x08002800,该地址内不能去读写数据,否则会造成代码奔溃。
在这里插入图片描述
此处还有个直观的方式查询代码所占FLASH,就是用创芯工坊的烧录器进行FLASH页面的读取,在上位机进行显示,可以直观的看到代码所占地址,以及在地址内的数据分布,同时基于代码安全性,该烧录器还可以进行代码的读保护和代码的高度加密,即使代码被反读也无法运行。实现代码和MCU的绑定。创芯工坊也与国民技术达成合作,基本支持目前国民所有MCU的加密离线烧录,本人在去年论坛的测评有幸获得一块,操作方面好用,有代码加密,离线烧录和远程代码交付的可以试一下。目前还有蓝牙无线烧录,但是本人还未拥有,以后拿到了给大家分享一下。
官网链接:点此跳转
以下为PW200读取MCU的FLASH页面:
在这里插入图片描述
可以直观看到代码的存放位置,右边是每一页的大小和地址,在测试FLASH时非常方便。

4. 通过代码进行一次FLASH的擦除和读写操作。此处我们参见一下官方的demo。

#include "main.h"

#include <stdio.h>

/**

 *  Flash_Program

 */

 

#define FLASH_PAGE_SIZE        ((uint16_t)0x800)

#define FLASH_WRITE_START_ADDR ((uint32_t)0x08010000)

#define FLASH_WRITE_END_ADDR   ((uint32_t)0x08018000)

 

/**

 * [url=home.php?mod=space&uid=247401]@brief[/url]  Main program.

 */

int main(void)

{

    uint32_t Counter_Num = 0;

    uint32_t Erase_Data  = 0x12345678;

    /* USART Init */

    USART_Config();

    printf("Flash Program Test Start\r\n");

    /* Program FLASH */

 

    /* Configures the Internal High Speed oscillator */

    if(FLASH_HSICLOCK_DISABLE == FLASH_ClockInit())

    {

        printf("HSI oscillator not yet ready\r\n");

        while(1);

    }

 

    /* Unlocks the FLASH Program Erase Controller */

    FLASH_Unlock();

 

    /* Erase */

    if (FLASH_COMPL != FLASH_EraseOnePage(FLASH_WRITE_START_ADDR))

    {

        while(1)

        {

            printf("Flash EraseOnePage Error. Please Deal With This Error Promptly\r\n");

        }

    }

 

    /* Program */

    for (Counter_Num = 0; Counter_Num < FLASH_PAGE_SIZE; Counter_Num += 4)

    {

        if (FLASH_COMPL != FLASH_ProgramWord(FLASH_WRITE_START_ADDR + Counter_Num, Erase_Data))

        {

            while(1)

            {

                printf("Flash ProgramWord Error. Please Deal With This Error Promptly\r\n");

            }

        }

    }

 

    /* Locks the FLASH Program Erase Controller */

    FLASH_Lock();

 

    /* Check */

    for (Counter_Num = 0; Counter_Num < FLASH_PAGE_SIZE; Counter_Num += 4)

    {

        if (Erase_Data != (*(__IO uint32_t*)(FLASH_WRITE_START_ADDR + Counter_Num)))

        {

            printf("Flash Program Test Failed\r\n");

            break;

        }

    }

 

    printf("Flash Program Test End\r\n");

 

    while (1)

    {

    }

}

 

/**

 * [url=home.php?mod=space&uid=247401]@brief[/url]  USART_Config.

 */

void USART_Config(void)

{

    GPIO_InitType GPIO_InitStructure;

    USART_InitType USART_InitStructure;

 

    GPIO_InitStruct(&GPIO_InitStructure);

    

    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE);

    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_USART1, ENABLE);

 

    GPIO_InitStructure.Pin        = GPIO_PIN_9;

    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;

    GPIO_InitStructure.GPIO_Alternate  = GPIO_AF4_USART1;

    GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);

 

    GPIO_InitStructure.Pin       = GPIO_PIN_10;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Input;

    GPIO_InitStructure.GPIO_Alternate  = GPIO_AF4_USART1;

    GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);

 

    USART_InitStructure.BaudRate            = 115200;

    USART_InitStructure.WordLength          = USART_WL_8B;

    USART_InitStructure.StopBits            = USART_STPB_1;

    USART_InitStructure.Parity              = USART_PE_NO;

    USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;

    USART_InitStructure.Mode                = USART_MODE_RX | USART_MODE_TX;

    USART_Init(USART1, &USART_InitStructure);

 

    USART_Enable(USART1, ENABLE);

}

因为官方的库函数是有状态返回的,为了测试FLASH擦写成功,代码中加了大量的USART状态打印,方便用户通过串口查看状态,在使用中屏蔽,几个重要的函数:

FLASH_ClockInit()


FLASH时钟的初始化。


FLASH_Unlock();///解锁FLASH



FLASH_Lock();///锁FLASH

这两个函数成对存在,操作FLASH前需解除锁定,完成后需锁定,否则可能因为程序的复位造成数据丢失。

FLASH_EraseOnePage();//擦除一页


FLASH_ProgramWord(uint32_t Address, uint32_t Data)//编程FLASH,一次操作4个字节。

重要的宏定义

#define FLASH_PAGE_SIZE        ((uint16_t)0x800)


#define FLASH_WRITE_START_ADDR ((uint32_t)0x08010000)


#define FLASH_WRITE_END_ADDR   ((uint32_t)0x08018000)

FLASH_PAGE_SIZE:每页的大小,因为此MCU的一页是2K,所以这里是0x800,如果是1K的改为0x400,

FLASH_WRITE_START_ADDR:写FLASH的首地址,改地址不可随意定义,要对照手册计算每一页的首地址,或者使用PW200读取FLASH后从FLASH映射中获取。
在这里插入图片描述
FLASH_WRITE_END_ADDR:页结束地址,对应开始地址,结束地址和开始地址都要选取整页的地址,可以是一页,可以是几页,但不能超出最大地址。

这样在例程中会计算需要写入多少个数据,并把整个页写满。

烧录复位后读取页面如下图所示:
在这里插入图片描述
在这里插入图片描述
此处可以看到FLASH 是以小端的形式写入,低位会写到FLASH的最前面,高位放在后面。注意:如果想保留该次数据,再下次烧写新的代码时不擦除该数据,在KEIL里面要设置只擦除所选:
在这里插入图片描述

5. 取出FLASH的数据很简单,直接对地址进行寻址就可:((__IO uint32_t)address。

6. 单片机的FLASH读写操作很简单,每家都有相应的库函数开放给用户使用,重点在于用户要清晰的了解单片机的FLASH结构,在使用时要正确的了解FLASH的每页地址,错误的写地址会造成不可估计的错误,本人在之前的项目中因不了解结构,直接套用函数,导致程序总是异常奔溃。

FLASH擦写速度测试:

在固件库的加持下,FLASH擦写异常方便,但是操作过FLASH的都知道,FLASH的操作十分耗时且占用总线,在程序中需要清晰的了解FLASH操作时的耗时问题,才可方便用户在编辑代码时预留出足够的时间用于FLASH的擦写。这里就测试一下N32G435的FLASH擦写速度。

首先将官方的demo中所有串口输出和状态检测的代码全部清除,只保留和FLASH相关的代码,同时初始化两个GPIO用于方便示波器捕捉时间。

PB0用于监测整个FLASH擦写操作的时间,PB1用于监测写FLASH的时间。GPIO的电平的操作均采用寄存器方式实现。

 while (1)



    {



GPIOB->PBSC = GPIO_PIN_0;



FLASH_Unlock();



/* Erase */



FLASH_EraseOnePage(FLASH_WRITE_START_ADDR);



GPIOB->PBSC = GPIO_PIN_1;



/* Program */



for (Counter_Num = 0; Counter_Num < FLASH_PAGE_SIZE; Counter_Num += 4)



{



FLASH_ProgramWord(FLASH_WRITE_START_ADDR + Counter_Num, Erase_Data);



}



/* Locks the FLASH Program Erase Controller */



GPIOB->PBC = GPIO_PIN_1;



FLASH_Lock();



GPIOB->PBC = GPIO_PIN_0;



Delay(50000);



}

在这里插入图片描述

在这里插入图片描述
上述过程皆为一页FLASH(2K)的擦写。通过左一可见一个完整的擦写过程,包括解锁,擦除一页,写一页,锁定四个步骤所用时间为54.6ms,只写一页所用时间为53ms。为了和手册对应,我又单独测试了只擦除一页所用的时间:
在这里插入图片描述
擦除的速度挺快的,只有834us(相对于写操作来说)。然后我们再找到官方的手册:
在这里插入图片描述
手册描述32位编程的时间典型值是100us,如果换算成一页,应该是512*100us=51.2ms。
考虑代码均采用库函数和测试环境不同,所测时间与手册还算吻合。
一页的擦除时间典型值是2ms。实际测试快了一倍还多,这个还是可以的。总体说来,手册的数据参考价值很高,后续有FLASH操作的用户了根据手册进行估算大概时间。
这次的文章就到这里,因本人后续的项目可能会使用国民技术的MCU,以后的相关开发经验会逐步上传,以此共勉,如果有需要其他外设的开发测试的朋友可留言,小密有时间会给大家更新,希望大家一起努力,共创国产单片机的开发生态。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/610715.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于C#制作一个鼠标连点器

秒杀抢券、压枪换弹都是网上冲浪的基本操作,制作一个鼠标连点器,从此在互联网所向披靡。 一、项目搭建1.1、创建1.2、界面设计 二、功能实现2.1、类型库调用2.2、窗口句柄定义2.3、线程处理2.4、快捷键 一、项目搭建 1.1、创建 打开Visual Studio&#xff0c;右侧选择创建新项…

ARM体系结构和RAM的工程搭建、程序编写

目录 工程搭建 程序编写 带标志位的加法ADC ADCS 跳转指令B\BL 栈的应用->叶子函数的调用过程 栈的应用->非叶子函数的调用过程 异常中断产生指令 协处理器指令 伪操作 安装交叉编译工具 Makefile 宏定义 预编译指令 申请一个字的空间 .word 申请多个字节空间 嵌套编程 方…

如何查询期刊的SCI分区

好消息是CSDN AI写作助手上线了 我不用自己一个字一个字去写SCI分区是啥&#xff08;x&#xff09; 然而—— 麻了还是自己写吧&#xff0c; 在人工智能这条路上&#xff0c;CSDN还是需要努力。 简单来说&#xff0c;我们做科研、发文章&#xff0c;肯定是需要比较的 谁的…

记录一次Mysql死锁事件(由Insert与uniqueKey导致)

| 导语记录一次于2023年01月23日遇到的死锁问题。 1、基础 1.1 数据库隔离级别 1.1.1RC READ COMMITTED&#xff1a;只能读取已经提交的数据&#xff1b;此时&#xff1a;允许幻读和不可重复读&#xff0c;但不允许脏读&#xff0c;所以RC隔离级别要求解决脏读&#xff1b; 1.1…

Mac下通过Docker安装ElasticSearch集群

1、安装ElasticSearch 使用docker直接获取es镜像&#xff0c;执行命令docker pull elasticsearch:7.7.0 执行完成后&#xff0c;执行docker images即可看到上一步拉取的镜像。 2、创建数据挂在目录&#xff0c;以及配置ElasticSearch集群配置文件 创建数据文件挂载目录 mkdir -…

如何快速掌握Facebook运营+独立站运营基础?

在当今数字化时代&#xff0c;Facebook运营和独立站运营成为许多企业和个人创业者的关键战略。通过巧妙地结合这两个渠道&#xff0c;你可以有效地推广品牌、吸引目标受众并实现商业目标。本文将为你介绍如何快速掌握Facebook运营和独立站运营的基础知识&#xff0c;为你的业务…

微服务组件之Eureka

1、什么是Eureka&#xff0c;为什么要有Eureka 在传统的RPC远程调用中&#xff0c;管理每个服务于服务之间依赖关系复杂&#xff0c;管理复杂&#xff0c;所以需要使用服务治理&#xff0c;管理服务于服务之间依赖关系&#xff0c;可以实现服务调用、负载均衡、容错等&#xf…

一文搞懂KMP算法!!!

一文搞懂KMP算法&#xff01;&#xff01;&#xff01; &#x1f341;什么是KMP算法?&#x1f341;什么是 next() 数组 和 前缀表?前缀表有什么作用呢最长公共前后缀如何计算前缀表 &#x1f680; 构造next数组&#x1f680; 使用next数组来做匹配 &#x1f341;什么是KMP算法…

基于SSM+Vue的旅游资源网站设计与实现

博主介绍&#xff1a; 大家好&#xff0c;我是一名在Java圈混迹十余年的程序员&#xff0c;精通Java编程语言&#xff0c;同时也熟练掌握微信小程序、Python和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架下…

我们不打价格战!大众的倔强

2023年即将过半&#xff0c;在价格战席卷市场的同时&#xff0c;汽车制造商必须在市场份额、销量、营收以及利润之间做出权衡。“无论如何&#xff0c;大众都不会参与中国市场的价格战。“本周&#xff0c;大众汽车首席运营官Ralf Brandstaetter表示。 这家曾经在中国市场长期占…

留学生ChatGPT的正确打开方式及推荐使用方式

ChatGPT是什么? ChatGPT可以代写论文吗&#xff1f; ChatGPT推荐打开方式是什么&#xff1f; 今天就为大家梳理一下火爆全网的ChatGPT在留学中的正确打开方式&#xff0c;让同学可以更好地体验ChatGPT带来的便利。 什么是Chat GPT&#xff1f; ChatGPT&#xff08;Chat G…

Office Visio 2016安装

哈喽&#xff0c;大家好。今天一起学习的是Visio 2016的安装&#xff0c;这是一个绘制流程图的软件&#xff0c;用有效的绘图表达信息&#xff0c;比任何文字都更加形象和直观。Office Visio 是office软件系列中负责绘制流程图和示意图的软件&#xff0c;便于IT和商务人员就复杂…

微信电脑版二维码( NATIVE 扫码支付)

后端代码 /** * 微信支付->扫码支付(模式二)->统一下单->微信二维码 * return */ PostMapping (value “/qrcode”) RequestLog(“微信支付二维码”) ApiOperation(“微信支付二维码”) AnonAccess public ResponseEntity wxpayPay(Validated RequestBody SysMember…

GreatSQL 8.0.32-24 今日发布

1.新增特性 1.1 SQL兼容性1.2 MGR1.3 性能优化1.4 安全 2.稳定性提升 3.其他调整 4.bug修复 5.GreatSQL VS MySQL 6.GreatSQL Release Notes GreatSQL 8.0.32-24版本发布&#xff0c;增加并行load data、&#xff08;逻辑 & CLONE&#xff09;备份加密、MGR读写节点可绑定…

MyBatis的创建和单表使用

前言&#xff1a; 之前我们了解到MySQL。接下来了解一下MyBatis&#xff0c;它不是一种数据库&#xff0c;那是什么呢和数据库有什么联系了&#xff1f; 目录 一&#xff1a;MyBatis的定义 二&#xff1a;MyBatis的创建 三&#xff1a;MyBatis的简单使用 3.1:准备工作 3.…

后端服务架构高性能设计之道

“N 高 N 可”&#xff0c;高性能、高并发、高可用、高可靠、可扩展、可维护、可用性等是后台开发耳熟能详的词了&#xff0c;它们中有些词在大部分情况下表达相近意思。本序列文章旨在探讨和总结后台架构设计中常用的技术和方法&#xff0c;并归纳成一套方法论。 前言 本文主…

视频采集到录制 - MP4生成

录制最终格式是MP4&#xff0c;视频流是采用H264编码流&#xff0c;音频是aac编码流 最终需要将两个流合并到一个文件里 采用的方案&#xff0c;是通过mp4v2的库&#xff0c;进行合并 原理很简单&#xff1a; 先创建文件&#xff0c;输入编码参数 需要创建视频流初始 也需要…

制造业在数字化时代如何应对挑战和机遇?

随着数字化时代的到来&#xff0c;制造业不可避免地会受到一些对应的挑战和机遇。以下是一些关键部分&#xff1a; 数字化转型&#xff1a;制造商已经采用数字技术来转变他们的运营。包括采用高级分析、自动化、人工智能 (AI) 和物联网 (IoT)。这些技术可以提高生产力、质量控制…

2.项目数仓、项目工具

项目数仓 数仓(Data Warehouse)是指用于存储和管理企业数据的一种大型数据库系统,以支持企业的决策分析活动。它采用了ETL(抽取、转化、加载)等技术来集成和清洗数据,并提供了灵活的查询和报表功能,使得分析师和决策者可以更好地理解企业的业务情况和趋势。 项目工…

基于三相坐标系状态方程的感应电动机起动动态计算(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…