Flash

前段时间有客户在官方社区反映i.MX RT1170下,使用官方SDK里FlexSPI驱动去擦写Flash时不能很好地支持全局中断。

客户项目里用了两块NOR Flash,分别挂在不同的 FlexSPI上,一块Flash用于存储XIP代码(FlexSPI1),另一块Flash用于存储项目资源数据(FlexSPI2),显然这样的设计原理上是没有问题的,那为什么使能了中断会出问题呢?今天就来分析下这个问题:

注: 客户测试的SDK版本为 2.12.1,对应的FlexSPI driver版本为2.3.6

一、为什么擦写Flash时经常需要关全局中断?

在具体分析客户问题之前,我们先来聊聊嵌入式应用里应对NOR Flash的擦写,为何大部分情况下都是要关闭全局中断(这里假设执行代码空间与擦写操作空间在同一个 Flash上,当然是在不同区域),这其实跟如下两个特性有关:

1.1 RWW特性(Read-While-Write)

RWW特性的意思是在Flash执行擦写命令进入Busy 状态期间(Flash内部状态寄存器 WIP位变状态1)还能否继续响应非操作区域的读访问。如果SR[WIP] = 1 时还能够支持读访问,则该Flash 支持RWW,反之则不支持RWW。

1.png

绝大部分Flash都是不支持RWW特性的,这就是为什么Flash擦写操作代码本身是需要重定向到RAM里去执行(尤其是回读SR[WIP]状态的代码)。

对于支持RWW特性的Flash,一般是以Block为单位,Flash擦写操作代码放在BlockX 里执行,则可以操作BlockX以外的其它Block 区域,且不需要做代码重定向。

现在你应该知道对于不支持RWW的Flash为什么擦写时需要关闭全局中断了,因为无法保证中断响应相关代码全都重定向到RAM里了,所以干脆在Flash擦写期间不响应任何中断。

1.2 SCLK Stop特性

SCLK Stop特性的意思是在Flash执行写入命令接受主设备传输过来的Page数据期间,如果总线上SCLK停止(一般情况是FlexSPI这一端的TXFIFO为空或者触发空条件),则Flash能否也暂停接受当前Page数据直到SCLK继续输出从而继续处理剩下的Page数据。

绝大部分Flash是不支持SCLK Stop特性的,因此在MCU端如果传输Page数据,需要一次性连续传输完成,一旦中途被打断,则两次不连续的Page数据传输可能无法得到想要的Page写入结果。这也是为何Flash写入期间我们需要关闭中断。

二、FlexSPI外设写操作设计

关于i.MX RT上的FlexSPI外设基本情况,以前有两篇旧文 《FlexSPI支持在Flash XIP原理》、《FlexSPI支持AHB方式写入Flash》,大家先读一下有个初步了解。

这里想重点说一下FlexSPI关于IPG方式写操作的设计,下图为FlexSPI外设的模块框图,绿色线标出了 IPG 方式写入的通路,这里大家可以看出,其中 IP_TX_FIFO 模块起了重要的数据缓冲作用,驱动里往 FLEXSPI->TFDRx 寄存器写入的 Page 数据会先被装载进 IP_TX_FIFO 里,然后再传输出去。

2.png

不同i.MX RT型号中IP_TX_FIFO大小不一样,目前有三种大小:128、256或1024 Bytes。

对于QuadSPI/OctalSPI NOR Flash来说,Page 大小一般是256 Bytes;对于 HyperBus Flash,Page 大小一般是 512 Bytes。所以在 i.MX RT10xx 上 IP_TX_FIFO 是不足以缓冲整个 Page 的,i.MX RT117x 上可以缓冲 QuadSPI/OctalSPI NOR 类型的 Page,i.MX RT118x/5xx/6xx 上则可以缓冲全部 NOR Flash 类型的 Page。

对于 Page 数据不能全部缓冲的情况,则需要一边传输一边缓冲。

3.png

在具体装载数据进 IP_TX_FIFO 时,主要涉及如下三个 FLEXSPI 寄存器,IP_TX_FIFO 一次只能被填入watermark level大小的数据,想要把全部 Page 数据填进 IP_TX_FIFO,需要分多次装载。只要 FLEXSPI->INTR[IPTXWE] 标志为 0, 即代表 IP_TX_FIFO 剩余空间大于等于 watermark level,那么就可以继续装载。

  • FLEXSPI->IPTXFCR[TXWMRK]  -- 设置一次装载进 IP_TX_FIFO 的数据长度(即 watermark level),8 Bytes为单位
  • FLEXSPI->TFDRx            -- 按 watermark level 长度填入 IP_TX_FIFO 装载数据
  • FLEXSPI->INTR[IPTXWE]     -- 触发 IP_TX_FIFO 的一次装载

4.png

三、客户问题及FlexSPI driver写操作流程

前面铺垫了这么多,终于来到客户遇到的 FlexSPI 驱动对于中断不支持的问题了。因为客户使用了两片Flash,所以不存在 RWW 限制问题,那剩下的原因就跟 SCLK Stop 特性有关,即 IP_TX_FIFO 并没有缓冲全部的 Page,导致 Page 传输过程被中断打断了,然后 IP_TX_FIFO 因为缓冲数据全部发完而使 FlexSPI 模块进入了 SCLK Stop 状态。

我们直接打开fsl_flexspi.c驱动文件,找到跟写操作相关的 FLEXSPI_TransferBlocking() 函数,在函数实现里可以发现,启动写传输时序的控制位 FLEXSPI->IPCMD[TRG] 是在 IP_TX_FIFO 填充动作 FLEXSPI_WriteBlocking() 函数之前被开启的,那这样的实现确实是不能够很好地支持中断的。

5.png

四、如何改进FlexSPI driver支持中断?

知道了原因所在,改起来也很简单。如果是QuadSPI/OctalSPI NOR Flash类型(Page=256 Bytes),在 i.MX RT117x 上,其 IP_TX_FIFO 大小为 256 Bytes,能够缓冲全部的 Page 大小,则可以先调用 FLEXSPI_WriteBlocking() 装载全部的 Page 数据,然后再开启 FLEXSPI->IPCMD[TRG] 去触发写传输时序,这时候就不怕被中断打断了,如下代码所示。

当然下面代码只是一个 workaround 式的实现示例,不是一个完整的解决方案,毕竟 FlexSPI 驱动要适配全部 i.MX RT 型号以及全部类型的 NOR Flash,此外还适用 NAND 型 Flash(Page 一般是 2KB),这时候需要根据情况拆分调用多次 FLEXSPI_WriteBlocking() 函数(不管怎样要保证启动写传输时序前,把 IP_TX_FIFO 先装满)。

status_t FLEXSPI_TransferBlocking(FLEXSPI_Type *base, flexspi_transfer_t *xfer)
{
    // 代码略去

    /* Start Transfer. */
    if ((xfer->cmdType == kFLEXSPI_Write) || (xfer->cmdType == kFLEXSPI_Config))
    {
        result = FLEXSPI_WriteBlocking(base, xfer->data, xfer->dataSize);
        base->IPCMD |= FLEXSPI_IPCMD_TRG_MASK;
    }
    else if (xfer->cmdType == kFLEXSPI_Read)
    {
        base->IPCMD |= FLEXSPI_IPCMD_TRG_MASK;
        result = FLEXSPI_ReadBlocking(base, xfer->data, xfer->dataSize);
    }
    else
    {
        base->IPCMD |= FLEXSPI_IPCMD_TRG_MASK;
    }

    // 代码略去
}

来源:恩智浦MCU加油站

免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

围观 13

关于STM32对内部Flash的保护

为了防止对Flash的非法访问,所有STM32的芯片都提供对Flash的保护,具体分为写保护和读保护。

如果对Flash设置了写保护,那就无法对Flash进行编程和擦除。在开发STM32的时候,如果出现这种情况,通常仿真器都支持对Flash进行解锁,像jlink,stlink等仿真器都支持这个功能。

在使用MDK进行调试的时候,可能会遇到如下图所示的报错信息,这时候就要排查Flash是不是被保护起来了。 

1.png

读保护即大家通常说的“加密”,是作用于整个Flash存储区域,相关文章:STM32等单片机程序加密的方法。一旦设置了Flash的读保护,内置的Flash存储区只能通过程序的正常执行才能读出,而不能通过下述任何一种方式读出:

  • 通过调试器(JTAG或SWD)

  • 从RAM中启动并执行的程序

写保护是以四页(1KB/页) Flash存储区为单位提供写保护,对被保护的页实施编程或擦除操作将不被执行,同时产生操作错误标志,读与写设置的效果见下表: 
当Flash读保护生效时,CPU执行程序可以读受保护的Flash区,但存在两个例外情况:

2.png 

  • 调试执行程序时

  • 从RAM启动并执行程序时 

STM32还提供了一个特别的保护,即对Flash存储区施加读保护后,即使没有启用写保护,Flash的第 0 ~ 3 页也将处于写保护状态,这是为了防止修改复位或中断向量而跳转到RAM区执行非法程序代码。 

Flash保护的相关函数   

FLASH_Unlock();   //Flash解锁 
FLASH_ReadOutProtection(DISABLE);  //Flash读保护禁止   
FLASH_ReadOutProtection(ENABLE);   //Flash读保护允许

STM32如何设置读保护和解除读保护?

读保护设置后将不能读出Flash中的内容。
如何设置读保护在程序的开头加入“设置读保护”的代码即可,每次运行代码时都检查一下,如果没有开就打开,如果打开了就跳过。其中,设置读保护的代码如下:

int main(void)
{  
   ...
   if (FLASH_GetReadOutProtectionStatus()!=SET)//检查设置读保护与否  
   {    
      FLASH_Unlock();         //写保护时可以不用这句话,可用可不用    
      FLASH_ReadOutProtection(ENABLE);     //设置读保护  
   }  
   ...
   while(1)  
   {    
   ...  
   }
}

上面的代码执行后,使用j-link就不能读出程序了,实现了代码读保护。需要注意的是,芯片读保护后无法再次烧写新的程序到Flash中,必须要解除读保护才可以。但是当解除读保护的时候STM32会自动擦除整个Flash,起到保护数据的作用。

通过代码解除Flash保护
解除读保护可以设置在按键里面,方便实现解锁,也可以设置在命令中。如下是解除读保护代码:

3.png

程序中设置一个按键或者命令,可以随时解除Flash的读保护,让芯片又可以重新烧录程序。如果没有留,还可以专门写一个程序,下载到RAM中去运行,用来解除读保护。

注意:执行后,Flash会自动全部擦除。

int main(void)
{
   Chip_Init();  
   FLASH_Unlock(); //不解锁FALSH也可设置读保护,可用可不用  
   FLASH_ReadOutProtection(DISABLE);
}

通过ST-Link Utility来解除Flash保护

在STLink连接目标板的情况下打开程序烧写软件ST-Link Utility,在菜单栏的Target下选择connect,因为这时候Flash已经被锁住了,能看到如下图所示的错误提示。

4.png

下面来操作如何解除Flash保护。

请确保当前已经正确连接了STLink和目标板,在菜单栏Target里打开Option Bytes...选项,发现在这里Read Out Protection选项是Enable,这个表示无法通过SWD读取STM32内部Flash的程序。

5.png

将Read Out Protection选项设置为Disable,并点击Apply。

这时候Flash已经成功解锁了,跟上文提到的解除Flash保护的结果一样,内部Flash已经被擦除了,如下图红框中所示。

6.png

完成以上步骤之后,在菜单栏Target下选择Disconnect断开与目标板连接。

重新进入MDK,可以正常对目标板烧写程序了。

通过ST-Link Utility来设置Flash保护

7.png

在菜单栏Target里打开Option Bytes...选项,可以看到下面有Flash sector protection选项。选择Select all之后,发现所有Page的Protection项都已经变成Write Protection了,只要选择Apply选项就可以对Flash进行写保护,如上图所示。

来源:STM32嵌入式开发

免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

围观 12

1、概述

ME32x系列是内嵌ARM Cortex™ M0/M3核的32位微控制器。该系列控制器由敏矽微电子有限公司自主开发,并具有自主知识产权。敏矽微电子的微控制器包括有通用MCU和专用SOC系列,具有非常高的性价比,是MCU产品升级换代和国外产品替代的最佳选择。通用功能有高精度ADC,CAN接口,I2S音频接口,UART串口,SPI接口,I2C总线接口,看门狗定时器(WDT),通用计数器/定时器。特殊接口包括人机界面控制器(LCD驱动,电容触摸按键)和马达控制功能模块。

EEPROM作为比较廉价和方便数据存储器,被广泛使用并且习惯思维。而MCU Flash与EEPROM相比,除使用方法略有差异外,作为数据存储器,所起的效果是一样的。

2、MCU Flash与EEPROM使用比较

擦除

擦除时间

编程

编程时间

硬件接口

擦写寿命

MCU Flash

扇区为单位擦除,擦除后数据为0xFF

5ms

32位word 编程

7us

通过寄存器接口设置编程,读Flash通过指针直接读

10万次

EEPROM

没有单独擦除功能

-

Byte编程

-

I2C接口

100万次

3、使用MCU Flash 存储数据举例

以ME32S003系列为例,下面说明如何使用MCU Flash 存储小量的数据(注意,本例重点在探讨实现的一个思路,程序调试请用户自行解决)。

ME32S003系列有32K Flash,我们拿出1K, 即两个扇区来存储数据,在这里约定一个数据存储单元为64 Bytes(包括标志)。

两个扇区有16个存储单元,换句话说,可以存储10万x 16 =160 次数据,远远超过EEPROM的寿命。

所有需要存储数据放在一个数据结构中,方便存储和提取数据:

#defineDATA_AREA_ADDRESS 62*512 //数据扇区起始地址
#defineDATA_AREA_SIZE 2*512 //两个扇区大小
#defineDATA_UINT_SIZE 64 //每一个存储单元大小,一定要整除扇区大小(512)
#defineDATA_UINT_FLAG 0x5555AAAA
typedef struct {
uint32_t flag;
uint32_t data1;
…
} data_uint_type;
voidflash_erase(uint32_t startaddr, uint32_t size)
{
uint32_t endaddr;
endaddr=startaddr+size;
     //erase sector
     while(startaddr<endaddr)
     {
              FMC->ADDR = startaddr; // setup addr
              FMC->CMD = 0x04; //Triggerprogramming
              while ((FMC->CMD &0x100)!=0);
              startaddr+=512;
     }
return;  
}
uint8_t flash_word_program(uint32_taddr, uint32_t worddata) //返回一个非0的数据当错误发生时
{
     //program word
              FMC->ADDR = addr; // set upaddr     
              FMC->DATA =worddata;
              FMC->CMD = 0x02; //Triggerprogramming
              while ((FMC->CMD &0x100)!=0);
              if (*(uint32_t *)addr== worddata)
      return 0;
else
      return 1;
}
data_uint_type* data_area_init(void)//返回一个指向数据单元的指针,空指针表示没有数据
{
data_uint_type* ptr;
ptr=get_last_data_uint_ptr();
if (((uint32_t) ptr==DATA_AREA_ADDRESS)&&(ptr->flag!==DATA_UINT_FLAG))
{
flash_erase(DATA_AREA_ADDRESS,DATA_AREA_SIZE);
ptr= null;
}
}
data_uint_type* get_last_data_uint_ptr(void)//返回一个指向数据单元的指针
{
uint32_tstartuintaddr,enduintaddr,temp;
startuintaddr= DATA_AREA_ADDRESS/DATA_UINT_SIZE;
enduintaddr= startuintaddr+DATA_AREA_SIZE/ DATA_UINT_SIZE-1;
while(startuintaddr!=enduintaddr)
{
              temp= (startuintaddr+ enduintaddr)>1;
              if ((data_uint_type*)(temp* DATA_UINT_SIZE)->flag==DATA_UINT_FLAG)
                       startuintaddr= temp;          
else
                enduintaddr= temp
}
startuintaddr =startuintaddr * DATA_UINT_SIZE;
if (((data_uint_type*)startuintaddr)->flag!=DATA_UINT_FLAG)
return (data_uint_type*) 0;
else
                {
                        If (startuintaddr< (DATA_AREA_ADDRESS+DATA_AREA_SIZE))
                                 {
                                          If  (((data_uint_type*)(startuintaddr+ DATA_UINT_SIZE)->flag==DATA_UINT_FLAG)
                                          return(data_uint_type*)(startuintaddr+ DATA_UINT_SIZE) ;
}else
return (data_uint_type*)(startuintaddr) ;
}
}
uint8_tstore_data_uint(data_uint_type* sur_data_ptr, data_uint_type* dst_data_ptr) //返回一个非0的数据当错误发生时
{
     uint32_t n,temp0,temp1,temp2,*dataptr;
     temp1= sizeof(data_uint_type) >>2;
if((temp1<<2)!= sizeof(data_uint_type))
     temp1++;
     temp2=(uint32_t) dst_data_ptr;
     dataptr=(uint32_t *) sur_data_ptr;
     //erase sector
     if ((DATA_AREA_ADDRESS==temp2)&&(dst_data_ptr->flag==DATA_UINT_FLAG))
     {
              flash_erase(DATA_AREA_ADDRESS, DATA_AREA_SIZE);//erase whole data sectors
     }
     for (n=0;n<temp1;n++)
     {
              if (flash_word_program(temp2, *dataptr++))
      return 1;
              temp2 +=4;
     }
return 0;
}

系统启动时,先调用data_area_init()函数,返回当前数据单元指针,你可以使用memory copy 复制数据到你的程序中。如果是空指针,你需要对你的数据赋予初值,并把它存储到数据区。

全局变量:

data_uint_typemydata;
data_uint_type * dataptr;
main(void)
{
…
dataptr=data_area_init();//初始化
if((uint32_t)dataptr==0) //空指针
{
//对mydata赋予初值
…
//存储数据到Flash 数据区
data_ptr =(data_uint_type *) DATA_AREA_ADDRESS;
store_data_uint(&mydata,data_ptr);
}
…
//任何时候,调用store_data_uint()把mydata数据存储到Flash
data_ptr++;
if ((uint32_t)data_ptr==DATA_AREA_ADDRESS)
data_ptr =(data_uint_type *) DATA_AREA_ADDRESS;
store_data_uint(&mydata,data_ptr);
…
//data_ptr永远指向当前Flash 数据
…
}

注意事项:

由于mydata的地址是编译器自动设定的,如果发生mydata地址不是word对齐地址,需要手动设置。总之,要确保mydata地址是word对齐的。

4、Revision History

来源:敏矽MCU
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:
cathy@eetrend.com)。

围观 41

智能化变革浪潮推动了更多物联网设备的应用整合,智能穿戴设备正趋于多元化的发展态势,不仅有智能手表/手环、TWS耳机等成熟产品的持续迭代,更有XR眼镜/头显等创新产品不断竞逐消费市场,力图开创一片新的蓝海。

智能穿戴设备让人们的生活更加高效便捷,受到了市场的热烈追捧。相关数据表明,2021年全球智能手表/手环市场出货量达2.1亿只,同比增长8%,2022年预计全球智能手表/手环市场出货量将增长28%,达到2.7亿只。TWS耳机同样热度不减,2021年全球TWS耳机市场销量为4.9亿对,2022年预计全球TWS耳机出货量有望达到6.1亿对。

“”2020年-2022年全球智能手表市场情况"
2020年-2022年全球智能手表市场情况

在智能穿戴设备“普及”与“升级”双线驱动的市场环境下,供应链创新如何满足市场不断增长的需求成为了业界的热议话题。

“”
演讲人:李嶷云先生
职务:兆易创新存储事业部市场主管

日前,在潮电智库举办的《穿戴存储芯片低功耗线上研讨会》上,兆易创新存储事业部市场主管李嶷云先生受邀参加活动,向参会的众多业界人士分享了智能穿戴应用的最新发展趋势以及兆易创新作为全球排名第一的无晶圆厂Flash供应商对于存储芯片的技术应用思考,共同探讨行业走向、推动产业创新。

智能穿戴产品种类越来越丰富,智能化的创新为整个行业带来了源源不断的活力。举个例子,智能手表/手环的功能正变得愈加丰富,除了常规的心率/血氧实时监测,还有诸如高分辨率屏幕从LCD升级到AMOLED、ECG/血糖/血压等健康医疗功能、BT/WIFI/UWB/GNSS等多种定位方式以及语音识别/人脸识别/智能控制等AI能力逐步加入其中,系统集成度更高,设计难度也随之增加。

“在这样的整体升级趋势下,终端客户对于元器件自然有了更严格的要求。以Flash存储器为例,除了小尺寸、低功耗这些我们熟知的要求之外,大容量和高性能也成为了客户的必选项。”李嶷云表示,“例如一些OEM客户在2021年大多是要求128Mb的NOR Flash产品,而现在对于NOR Flash的容量要求甚至达到了1Gb,增长非常迅猛,同时对于数据吞吐能力的要求也是翻倍的增长。”

“智能手表应用不断升级,功能愈加丰富"
智能手表应用不断升级,功能愈加丰富

而纵观TWS耳机应用,新一代蓝牙标准LE Audio的持续落地、显著提高舒适度体验的各类降噪与智能技术、以及产品整体续航能力的提升成为了业界未来的突破重点。

李嶷云称:“像LE Audio已经是整个业界的共识,在一些客户的高端型号已经显现。相较传统蓝牙音频,LE Audio采用了新的编解码LC3,支持多重串流,还增加了全新的辅助听力与音频广播功能,带来更好的音质、更小的传输功耗、更低的延时以及创新的应用想象空间,并需要存储器件具备更大的代码存储空间、更快的读写速度以及更稳定可靠的存储表现,而这恰恰是兆易创新存储产品的一贯优势。”

““190亿颗”出货里程碑达成!兆易创新Flash打造次世代智能穿戴存储基石"

为了应对不断增长的挑战,兆易创新经过多年的技术与市场沉淀,可以向业界提供覆盖512Kb-2Gb等多种容量规格的量产型SPI NOR Flash产品,能够满足不同客户对于大容量存储的需求。

另外,针对高性能的产品需求,兆易创新还推出了GD25LF、GD25LT、GD25LX等产品系列,其拥有高速4通道及兼容xSPI规格8通道的数据传输能力,提供最高400MB/s的数据吞吐速率,成为了业界高性能NOR Flash解决方案的标杆,助力客户轻松搞定各种应用场景。

在广泛的市场机遇与不断修炼“内功”的努力下,兆易创新Flash产品深受客户青睐、一路高歌猛进,如今累计出货量已超过190亿颗,其中NOR Flash市场份额更是排名全球前三。

李嶷云表示:“190亿颗出货量里程碑代表了兆易创新Flash在过去十多年的努力与成果。在万物智联时代,我们依然保持初心、迎接新的挑战,致力打造更优秀的产品、提供更全面的服务。”

目前,兆易创新Flash在超低功耗、超小封装等技术工艺上持续打磨,例如采用WLCSP超小封装的NOR Flash产品已经上市,对整个系统PCB的面积缩减有极大帮助;主打超低功耗的1.2V产品系列也即将面世,可显著延长电池寿命。这些优异的特性使得兆易创新Flash成为了次世代智能穿戴应用打造高集成度、低功耗与高性能系统的存储基石,为行业客户赋能更多价值。

来源:兆易创新GigaDevice
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

围观 15

如果你还不了解什么是STM32对其Flash的保护,那么今天就来给你讲解一下什么是STM32的Flash保护!

01、什么是Flash?

STM32的FLASH组织结构,可能因不同系列、型号略有不同。比如大家熟悉的STM32F1中小容量一页大小只有1K,而F1大容量一页有2K。

还比如有些系列以扇区为最小单元,有的扇区最小16K,有的128K不等。

通常Flash包含几大块,这里以F40x为例:

  • 主存储器:用来存放用户代码或数据。

  • 系统存储器:用来存放出厂程序,一般是启动程序代码。

  • OTP 区域:一小段一次性可编程区域,供用户存放特定的数据。

  • 选项字节:存放与芯片资源或属性相关的配置信息。

“讲讲STM32单片机Flash的读保护和写保护"

02、什么是STM32对内部Flash的保护?

所有的STM32芯片都会提供对Flash的保护,防止对Flash的非法访问,分为:写保护和读保护。

1、读保护就是大家通常说的“加密”,作用于整个Flash存储区域。如果一旦设置了Flash的读保护,那么单片机内置的Flash存储区就只能通过程序的正常执行才能读出,而不能通过下述方式读出:

(1) 使用调试器(JTAG或SWD);
(2)从内存RAM中启动并执行的程序;

2、写保护是以四页(1KB/页) Flash存储区为单位提供写保护,如果对Flash设置了写保护,那么就无法对Flash进行编程和擦除,而且同时产生操作错误标志。 当出现下图标志的时候,就要检查Flash是否被保护起来了。

“讲讲STM32单片机Flash的读保护和写保护"

03、读保护与写保护的相关效果

当设置读保护与写保护时,其效果如下图所示:

“讲讲STM32单片机Flash的读保护和写保护"

1)flash保护的相关函数

“讲讲STM32单片机Flash的读保护和写保护"

2)STM32如何设置读保护?

我们只需要在程序开头加入“设置读保护”的代码就可以,这样就可以在每次运行代码的时候都检查一下,如果没有开的话就打开,如果开了就跳过。下面是读保护的代码:

“讲讲STM32单片机Flash的读保护和写保护"

当我们在程序的开头执行了上面的代码之后,使用j-link就不能在读出程序了,这样就实现了读保护。

3)如何通过代码解除Flash保护

解除读保护可以下面代码来进行解除,我们为了方便解锁,可以设置一个按键。

“讲讲STM32单片机Flash的读保护和写保护"

来源:玩转单片机与嵌入式
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

围观 1667

本文将介绍如何拆焊Flash芯片,设计及制作相应的分线板。了解对嵌入式设备的非易失性存储的简单有效攻击手段。这些攻击包括:

  • 读取存储芯片内容

  • 修改芯片内容

  • 监视对存储芯片的读取操作并远程修改(中间人攻击)

想想,当你拆开一个嵌入式产品,却被挡在Flash之外,好奇的你一定想对它一探究竟。

那么,下面我们就开始。

拆焊Flash芯片

为了读取Flash芯片的内容,有以下两个基本途径:

  • 直接将导线连接到 芯片的引脚

  • 把芯片拆下来,插到另一块板子上

下面介绍的Flash为BGA(球形栅格阵列)封装——无外露引脚。因此,只能选择拆焊的方法。

“图:目标芯片"
图:目标芯片

拆焊法的优点:

  • 可避免对电路板上其他器件造成影响;

  • 可以很容易看到芯片底部的布线;

  • 可用其他芯片或微控制器代替原芯片。

一些不便之处:

  • 电路在缺少完整器件的情况下无法运行;

  • 在拆卸过程中,一些邻近器件可能被损坏;

  • 如果操作不恰当,Flash本身可能毁坏。

OK,拆焊是吧?你看,下图所示的热风枪简直就是神器。只要将芯片周围加热,便可以很容易地拿下芯片:

“图:热风枪拆焊"
图:热风枪拆焊

这种办法简单、快速只是可能伤及无辜——焊掉邻近的元件,所以,务必小心翼翼。

下图显示芯片拆下后PCB的布线。观察图片,猜想底部的两列引脚为空引脚,因为他们压根就没接入电路。

“图:拆焊下来后"
图:拆焊下来后

用KiCAD定制分线板

现在该做什么?BGA封装简直就是一团糟,依然无法外接导线。

一种可行的方法是制作分线板。通常,分线板是将芯片的所有针脚的位置“镜像”下来,这样就能将芯片的引脚引接出来。

为此,我们首先要搜集芯片的相关信息。大多数情况下,芯片的型号都印制在芯片上,这样我们就很容易识别。如上图,芯片上第一行为MXIC代表Macronix International公司,第二行为芯片的具体型号MX25L3255EXCI datasheet 。以下为datasheet资料:

“图:针脚排布"
图:针脚排布

 PCB的设计可由KiCAD ,常用的EDA软件实现。

    分线板的设计过程与其他PCB板一样:

  • 新建电路板,画出电路简图,标明元器件的具体型号

  • 确定芯片的具体尺寸

根据之前datasheet的资料。我们添加1个4×6的网格作为整个芯片的BGA封装,2个1×4的网格作为连接芯片8个有效引脚的接线柱。最后一步是,用线路将这些器件连接起来:

“图:step2"
图:step2

转接板的设计到此为止,接下来是如何把设计转化成的PCB。

PCB制作

PCB就像是由两层铜和一层基板压制成的三明治,导线分布在铜上面。

根据制作流程,分为:

  • 蚀刻法

  • 数控铣法

以下为两种方法的具体步骤。

蚀刻法

蚀刻,即是用化学药品逐步除去铜的过程。我们先用油墨保护覆铜板上的线路及要保留下来的铜。

1、首先,用热转印法制作PCB。PCB电路图用激光打印机打印在亮光纸上。然后,把亮光纸紧贴在覆铜板上,加热和施以压力,使亮光纸上的电路图转印到覆铜板上。通常,这个过程用熨衣服的熨斗即可完成,但是专用的压制器会使加热及受力更加均匀,更容易成功。

2、接下来是蚀刻,将整块PCB板浸没在腐蚀液,以此来去除多余的铜。

蚀刻后的分线板,转印的墨粉还附着在上面:

“图:step3"
图:step3

除去墨粉后:

“图:step4"
图:step4

现在可以准备手工焊接了。微型焊接与正常焊接一样,只是器件的尺寸极小,因此需要借助显微镜。

此外,传统的焊接用的是线状的焊锡丝,而BGA微型焊接用的是锡球。

“图:step5"
图:step5

接下来,开始重整锡球:

  • 将一个新的锡球放置在凹槽上,加热,熔化锡球;

  • 校准芯片和板子;

  • 回流。

“图:step6"
图:step6

锡球重整完成:

“图:step7"
图:step7

芯片焊接完成后的最终结果:

“图:step8"
图:step8

数控铣

作为替代方法,数控铣仅是将需要的线路和剩余的铜隔离开来而已。

(1)5X5的BGA通常用于制作 PCB,而4X6的常用于分线板。我们设计5X5的是为了该分线板可以直接插接在通用EEPROM 编程器的ZIF插槽里,电路简图如下:

“图:step9"
图:step9

(2)芯片的尺寸与前面设计的4X6的一样,只是网格变成5X5,板上的布线也稍显复杂:

“图:step10"
图:step10

(3)由于KiCAD无法直接生成与数控铣兼容的目标文件,因此,我们用Flatcam接收Gerber文件并确定数控铣隔离的导线的路径:

“图:step11"
图:step11

“图:step12"
图:step12

(4)接下来将生成的STL文件导入bCNC——数控铣的终端控制程序,如下图所示:

“图:step13"
图:step13

雕刻过程中:

“图:step14"
图:step14

(5)板子雕刻完成:

“图:step15"
图:step15

最终结果:

“图:step16"
图:step16

(6)下一步,涂覆阻焊层,保护铜不被氧化,并用紫外灯固化:

“图:step17"
图:step17

“图:step18"
图:step18

(7)阻焊层覆盖了BGA的铜片及1X4的接线柱,我们得刮掉这个薄层,使铜片露出来:

“图:step19"
图:step19

(8)给各个节点焊锡:

“图:step20"
图:step20

“图:step21"
图:step21

(9)回到数控铣,打孔,切削PCB的边缘:

“图:step22"
图:step22

“图:step23"
图:step23

(10)最终成品,BGA焊接在板子上,准备插到EEPROM编程器上:

“图:step24"
图:step24

结论

了解了如何拆焊Flash芯片和如何设计PCB,以及制作PCB的两种不同方法。

来源:STM32嵌入式开发
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

围观 37

关于STM32对内部Flash的保护

为了防止对Flash的非法访问,所有STM32的芯片都提供对Flash的保护,具体分为写保护和读保护。

如果对Flash设置了写保护,那就无法对Flash进行编程和擦除。在开发STM32的时候,如果出现这种情况,通常仿真器都支持对Flash进行解锁,像jlink,stlink等仿真器都支持这个功能。

在使用MDK进行调试的时候,可能会遇到如下图所示的报错信息,这时候就要排查Flash是不是被保护起来了。

“”

读保护即大家通常说的“加密”,是作用于整个Flash存储区域。一旦设置了Flash的读保护,内置的Flash存储区只能通过程序的正常执行才能读出,而不能通过下述任何一种方式读出:

  • 通过调试器(JTAG或SWD)
  • 从RAM中启动并执行的程序

写保护是以四页(1KB/页) Flash存储区为单位提供写保护,对被保护的页实施编程或擦除操作将不被执行,同时产生操作错误标志,读与写设置的效果见下表:

“”

当Flash读保护生效时,CPU执行程序可以读受保护的Flash区,但存在两个例外情况:

  • 调试执行程序时
  • 从RAM启动并执行程序时

STM32还提供了一个特别的保护,即对Flash存储区施加读保护后,即使没有启用写保护,Flash的第 0 ~ 3 页也将处于写保护状态,这是为了防止修改复位或中断向量而跳转到RAM区执行非法程序代码。

Flash保护的相关函数

FLASH_Unlock();   //Flash解锁 
FLASH_ReadOutProtection(DISABLE);  //Flash读保护禁止   
FLASH_ReadOutProtection(ENABLE);   //Flash读保护允许

STM32如何设置读保护和解除读保护?

读保护设置后将不能读出Flash中的内容。

如何设置读保护

在程序的开头加入“设置读保护”的代码即可,每次运行代码时都检查一下,如果没有开就打开,如果打开了就跳过。其中,设置读保护的代码如下:

int main(void)
{
  ...
  if (FLASH_GetReadOutProtectionStatus()!=SET)//检查设置读保护与否
  {
    FLASH_Unlock();         //写保护时可以不用这句话,可用可不用
    FLASH_ReadOutProtection(ENABLE);     //设置读保护
  }
  ...
  while(1)
  {
    ...
  }
}

上面的代码执行后,使用j-link就不能读出程序了,实现了代码读保护。需要注意的是,芯片读保护后无法再次烧写新的程序到Flash中,必须要解除读保护才可以。但是当解除读保护的时候STM32会自动擦除整个Flash,起到保护数据的作用。

通过代码解除Flash保护

解除读保护可以设置在按键里面,方便实现解锁,也可以设置在命令中。如下是解除读保护代码:

void Off_Protect(void) //关闭保护
{
if(FLASH_GetReadOutProtectionStatus() != RESET)
  {
    FLASH_Unlock(); //不解锁FALSH也可设置读保护,可用可不用
    FLASH_ReadOutProtection(DISABLE);
    FLASH_Lock();   //上锁
  }
}

程序中设置一个按键或者命令,可以随时解除Flash的读保护,让芯片又可以重新烧录程序。如果没有留,还可以专门写一个程序,下载到RAM中去运行,用来解除读保护。

注意:执行后,Flash会自动全部擦除。

int main(void)
{
Chip_Init();
  FLASH_Unlock(); //不解锁FALSH也可设置读保护,可用可不用
  FLASH_ReadOutProtection(DISABLE);
}

通过ST-Link Utility来解除Flash保护

在STLink连接目标板的情况下打开程序烧写软件ST-Link Utility,在菜单栏的Target下选择connect,因为这时候Flash已经被锁住了,能看到如下图所示的错误提示。

“”

下面来操作如何解除Flash保护。

请确保当前已经正确连接了STLink和目标板,在菜单栏Target里打开Option Bytes...选项,发现在这里Read Out Protection选项是Enable,这个表示无法通过SWD读取STM32内部Flash的程序。

“”

将Read Out Protection选项设置为Disable,并点击Apply。

这时候Flash已经成功解锁了,跟上文提到的解除Flash保护的结果一样,内部Flash已经被擦除了,如下图红框中所示。

“”

完成以上步骤之后,在菜单栏Target下选择Disconnect断开与目标板连接。

重新进入MDK,可以正常对目标板烧写程序了。

通过ST-Link Utility来设置Flash保护

“”

在菜单栏Target里打开Option Bytes...选项,可以看到下面有Flash sector protection选项。选择Select all之后,发现所有Page的Protection项都已经变成Write Protection了,只要选择Apply选项就可以对Flash进行写保护,如上图所示。

本文转载自:STM32嵌入式开发
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:
cathy@eetrend.com)。

围观 247

页面

订阅 RSS - Flash