K3xx开发指南-C40读写
提示:仅供学习参考,个人记录所用
前言
参考文章链接:
https://xcnm.net/archives/nxpying-yong-bi-ji-yi-s32kdsdui-s32k3de-lian-jie-wen-jian-ji-nei-cun-jie-xi
- 扇区
块由大小分别为 8KB 和 64KB 的扇区和超级扇区组成。使用锁定功能可保护这些扇区不受写入或擦除操作的影响。块最后的256 KB 部分具有扇区保护功能,而其余部分则具有超级扇区保护。
这里作者发现NXP的Dflash(块2或块4)没有超级扇区的概念,只有Pflash才有
- 擦除
擦除操作是指将扇区或块中的所有位设置为1的流程。最小擦除单位可以是扇区,扇区大小为8KB。要擦除扇区或块,必须在擦除操作之前将其解锁。 - 写入
注意每次写入必须以8字节为单位且写入地址必须是八字节对齐否则会出现数据被覆盖的情况,每次最多写入128个字节即4页。
编程操作将位的逻辑值从1改为0,这意味着不允许从0改为1的编程操作,并且在执行任何编程操作之前需要擦除 Flash 存储器。 - 对于读取操作,不必考虑锁定或解锁扇区。
- 解锁
5.1 超级扇区的锁定和解锁流程由 PFCBLKn SSPELOCKn 寄存器控制,扇区的锁定和解锁流程由PFCBLKn SPELOCKn 寄存器控制。
5.2 PFCBLKn_SSPELOCKn 寄存器有 12 个可用位,其中每个位对应于一个超级扇区,同样,PFCBLKn_SPELOCKn 寄存器有 32个可用位,对应于 32 个可用扇区。如果需要执行解锁流程来允许编程或擦除操作,则应将相应的寄存器
PFCBLKn SSPELOCKn 或PFCBLKn SPELOCKn从1改为0,向 PFCBLK SPELOCKn 或PFCBLKn SSPELOCKn 的任何位写入1将锁定扇区或超级扇区,以防编程和擦除操作。
5.3 PFCBLKn SSPELOCKn 和 PFCBLKn SPELOCKn 寄存器所有位的 out ofreset 值为 1,这意味着所有扇区在复位后都受到保护,不受编程和擦除操作的影响。
提示:以下是本篇文章正文内容,下面示例可供参考
一、C40驱动
二、C40内存分配
1.查看当前芯片内存配置
三、C40读写
参考链接:
https://blog.youkuaiyun.com/kk_willbegood/article/details/134536613?spm=1001.2014.3001.5506
- 写
#define SECTORLEN 8192U
C40_Ip_StatusType C40_Ip_WriteData(const uint32 startAddr,
const uint8 *WData,
const uint32 WLen)
{
uint8_t FLS_MASTER_ID=2;//block,Data Flash的块区是2或4,具体看上面c40_IP_CFG.h
uint8 index = 0u;
uint8 lessWriteLen = 8u;
uint8 aDataBuf[8u] = {0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu};
uint32 writeDataLen = 0u;
C40_Ip_StatusType C40Status;
C40_Ip_VirtualSectorsType VirtualSector;
C40_Ip_VirtualSectorsType endVirtualSector;
//The program flash start address is 0x400000u, 32 is the program flash VirtualSector begin
/* Get virtual Sector number from address */
VirtualSector = C40_Ip_GetSectorNumberFromAddress(startAddr);//(startAddr - 0x400000u)/SECTORLEN + FLS_MAX_DATA_SECTOR;
endVirtualSector = C40_Ip_GetSectorNumberFromAddress(startAddr + WLen);//((startAddr + WLen) - 0x400000u) / SECTORLEN + FLS_MAX_DATA_SECTOR;
while(VirtualSector <= endVirtualSector) //******循环解锁 要写的扇区
{
if(STATUS_C40_IP_SECTOR_PROTECTED == C40_Ip_GetLock(VirtualSector))
{
C40_Ip_ClearLock(VirtualSector, 0);
}
VirtualSector++;
}
//Turn off all interrupts
INT_Interrupts_Disable();
/* Erase sector */
while(VirtualSector <= endVirtualSector) //******循环解锁 要擦除扇区
{
C40_Ip_MainInterfaceSectorErase(VirtualSector, FLS_MASTER_ID);
do
{
C40Status = C40_Ip_MainInterfaceSectorEraseStatus();
}
while (STATUS_C40_IP_BUSY ==C40Status);
VirtualSector++;
}
if(WLen & (lessWriteLen - 1)) //******对8(7-1)求余数: 84余4,有余数进if分支
{
/*if write data more than 8 bytes*/ //******写的数据多余8 即不能被8整除,但又大于8 :9-15 17-23 25-31 ......
if(WLen > lessWriteLen)
{
writeDataLen = WLen - (WLen & (lessWriteLen - 1)); //******减去余数,先写入8的整数倍
C40Status=C40_Ip_MainInterfaceWrite(startAddr,writeDataLen,WData, FLS_MASTER_ID);
if(STATUS_C40_IP_SUCCESS == C40Status)
{
do
{
C40Status = C40_Ip_MainInterfaceWriteStatus();//******检查C40_IP_MainInterfaceWrite功能启动的硬件程序的状态。这里会清0 EHV
}
while (STATUS_C40_IP_BUSY == C40Status);//******等写入完成 连续写入要等待
} //******这里主要是延时,虽然C40_Ip_MainInterfaceWrite返回成功,但是EHV再次调用返回错误,EHV仍未1。所以返回的成功是指上一次操作成功,但Flash状态不一定可以执行下一次操作
else
return C40Status; //写入失败,返回错误码
if(STATUS_C40_IP_SUCCESS == C40Status) //******写入余数数据
{
for(index = 0u; index < (WLen & (lessWriteLen - 1)); index++)
{
aDataBuf[index] = WData[writeDataLen + index]; //******前面的填充要写的数据,后面的默认是0xff
}
C40Status=C40_Ip_MainInterfaceWrite(startAddr+writeDataLen,8u,aDataBuf,FLS_MASTER_ID);
if(STATUS_C40_IP_SUCCESS == C40Status)
{
do
{
C40Status = C40_Ip_MainInterfaceWriteStatus();//******检查C40_IP_MainInterfaceWrite功能启动的硬件程序的状态。这里会清0 EHV
}
while (STATUS_C40_IP_BUSY == C40Status);//******等写入完成 连续写入要等待?
} //******这里主要是延时,虽然C40_Ip_MainInterfaceWrite返回成功,但是EHV再次调用返回错误,EHV仍未1。所以返回的成功是指上一次操作成功,但Flash状态不一定可以执行下一次操作
else
return C40Status; //写入失败,返回错误码
}
else
return C40Status; //返回错误码
}
else //******写的少于8字节 比如1-7字节
{
for(index = 0u; index < WLen; index++)
{
aDataBuf[index] = WData[writeDataLen + index]; //******前面的填充要写的数据,后面的默认是0xff
}
C40Status=C40_Ip_MainInterfaceWrite(startAddr+writeDataLen,8,aDataBuf,FLS_MASTER_ID);
if(STATUS_C40_IP_SUCCESS == C40Status)
{
do
{
C40Status = C40_Ip_MainInterfaceWriteStatus();//******检查C40_IP_MainInterfaceWrite功能启动的硬件程序的状态。这里会清0 EHV
}
while (STATUS_C40_IP_BUSY == C40Status);//******等写入完成 连续写入要等待?
} //******这里主要是延时,虽然C40_Ip_MainInterfaceWrite返回成功,但是EHV再次调用返回错误,EHV仍未1。所以返回的成功是指上一次操作成功,但Flash状态不一定可以执行下一次操作
else
return C40Status; //写入失败,返回错误码
}
}
else //******对8(7-1)求余数: 80余0,无余数进else分支。
{
C40Status=C40_Ip_MainInterfaceWrite(startAddr,WLen,WData, FLS_MASTER_ID);
if(STATUS_C40_IP_SUCCESS == C40Status)
{
do
{
C40Status = C40_Ip_MainInterfaceWriteStatus();//******检查C40_IP_MainInterfaceWrite功能启动的硬件程序的状态。这里会清0 EHV
}
while (STATUS_C40_IP_BUSY == C40Status);//******等写入完成 连续写入要等待?
} //******这里主要是延时,虽然C40_Ip_MainInterfaceWrite返回成功,但是EHV再次调用返回错误,EHV仍未1。所以返回的成功是指上一次操作成功,但Flash状态不一定可以执行下一次操作
else
return C40Status; //写入失败,返回错误码
}
//Enable all interrupts
INT_Interrupts_Enable();
return C40Status;
}
- 读
/* Read data */
/* Read data */
C40Status = C40_Ip_Read(FLS_SECTOR_ADDR, FLS_BUF_SIZE, RxBuffer);
总结
仅供个人学习使用,thanks!