一、WPS写保护方式(部分flash支持)
1.status reg3 WPS值1
int WinBand_Set_WPSBit(int bLock)
{
unsigned char ubStatus = 0;
SPI_Flash_Cmd(0x15, 1, &ubStatus, 1);
if(bLock) {
ubStatus |= 0x4;
} else {
ubStatus &= ~0x4;
}
printf("Apk_WinBand_Check_WPSBit:0x%x\r\n", ubStatus);
return SPI_Flash_Cmd(0x11, 0, &ubStatus, 1);
}
2.global block lock, 发0x7E命令锁定整个flash
int WinBand_Set_GlobalLock(int bLock)
{
int ret = 0;
if(bLock) {
ret = SPI_Flash_Cmd(0x7E, 0, NULL, 0);
} else {
ret = SPI_Flash_Cmd(0x98, 0, NULL, 0);
}
return ret;
}
3.解锁不需要锁定的block:发0x39命令+地址
int WinBand_Set_BlockLock(unsigned int Addr, int bLock)
{
int ret = 0;
char cData[4] = {0};
cData[0] = (Addr>>16) &0xff;
cData[1] = (Addr>>8) &0xff;
cData[2] = (Addr>>0) &0xff;
if(bLock) {
ret = SPI_Flash_Cmd(0x36, 0, cData, 3);
} else {
ret = SPI_Flash_Cmd(0x39, 0, cData, 3);
}
return ret;
}
//cmd为读时,pData为读buffer,iSize为需读取的字节数
//cmd为写时,pData为写buffer,iSize为需写入的字节数
int SPI_Flash_Cmd(unsigned char cmd, int bRead, char* pData, int iSize)
{
int i = 0;
MS_BOOL bRet = TRUE;
DEBUG_SER_FLASH(E_SERFLASH_DBGLV_DEBUG, printk("%s() in\n", __FUNCTION__));
if(bRead) {
MS_U8 *u8ptr = pData;
HAL_SERFLASH_SelectReadMode(E_FAST_MODE);//set normal mode(1-1-1)
HAL_FSP_WriteBufs(0, cmd);
FSP_WRITE_MASK(REG_FSP_WBF_SIZE,REG_FSP_WBF_SIZE0(1),REG_FSP_WBF_SIZE0_MASK);
FSP_WRITE_MASK(REG_FSP_WBF_SIZE,REG_FSP_WBF_SIZE1(0),REG_FSP_WBF_SIZE1_MASK);
FSP_WRITE_MASK(REG_FSP_WBF_SIZE,REG_FSP_WBF_SIZE2(0),REG_FSP_WBF_SIZE2_MASK);
FSP_WRITE_MASK(REG_FSP_RBF_SIZE,REG_FSP_RBF_SIZE0(iSize),REG_FSP_RBF_SIZE0_MASK);
FSP_WRITE_MASK(REG_FSP_RBF_SIZE,REG_FSP_RBF_SIZE1(0),REG_FSP_RBF_SIZE1_MASK);
FSP_WRITE_MASK(REG_FSP_RBF_SIZE,REG_FSP_RBF_SIZE2(0),REG_FSP_RBF_SIZE2_MASK);
FSP_WRITE_MASK(REG_FSP_CTRL,REG_FSP_ENABLE,REG_FSP_ENABLE_MASK);
FSP_WRITE_MASK(REG_FSP_CTRL,REG_FSP_NRESET,REG_FSP_RESET_MASK);
FSP_WRITE_MASK(REG_FSP_CTRL,REG_FSP_INT,REG_FSP_INT_MASK);
FSP_WRITE_MASK(REG_FSP_CTRL,REG_FSP_2NDCMD_OFF,REG_FSP_2NDCMD_MASK);
FSP_WRITE_MASK(REG_FSP_CTRL,REG_FSP_3THCMD_OFF,REG_FSP_3THCMD_MASK);
FSP_WRITE_MASK(REG_FSP_CTRL,REG_FSP_FSCHK_OFF,REG_FSP_FSCHK_MASK);
FSP_WRITE_MASK(REG_FSP_TRIGGER,REG_FSP_FIRE,REG_FSP_TRIGGER_MASK);
bRet &= _HAL_FSP_WaitDone();
for(i=0; i<iSize; i++) {
*(u8ptr + i) = HAL_FSP_ReadBufs(i);
}
DEBUG_SER_FLASH(E_SERFLASH_DBGLV_DEBUG, printk("%s() out\n", __FUNCTION__));
if(bRet == TRUE)
return 0;
return -1;
} else {
HAL_FSP_WriteBufs(0,SPI_CMD_WREN);
HAL_FSP_WriteBufs(1,cmd);
for(i=0; i<iSize; i++) {
HAL_FSP_WriteBufs(2+i,(MS_U8)pData[i]);
//printf("write data [%d]: 0x%x\n", i, pData[i]);
}
HAL_FSP_WriteBufs(2+iSize,SPI_CMD_RDSR);
FSP_WRITE_MASK(REG_FSP_WBF_SIZE,REG_FSP_WBF_SIZE0(1),REG_FSP_WBF_SIZE0_MASK);
FSP_WRITE_MASK(REG_FSP_WBF_SIZE,REG_FSP_WBF_SIZE1((1+iSize)),REG_FSP_WBF_SIZE1_MASK);
FSP_WRITE_MASK(REG_FSP_WBF_SIZE,REG_FSP_WBF_SIZE2(1),REG_FSP_WBF_SIZE2_MASK);
FSP_WRITE_MASK(REG_FSP_RBF_SIZE,REG_FSP_RBF_SIZE0(0),REG_FSP_RBF_SIZE0_MASK);
FSP_WRITE_MASK(REG_FSP_RBF_SIZE,REG_FSP_RBF_SIZE1(0),REG_FSP_RBF_SIZE1_MASK);
FSP_WRITE_MASK(REG_FSP_RBF_SIZE,REG_FSP_RBF_SIZE2(1),REG_FSP_RBF_SIZE2_MASK);
FSP_WRITE_MASK(REG_FSP_CTRL,REG_FSP_ENABLE,REG_FSP_ENABLE_MASK);
FSP_WRITE_MASK(REG_FSP_CTRL,REG_FSP_NRESET,REG_FSP_RESET_MASK);
FSP_WRITE_MASK(REG_FSP_CTRL,REG_FSP_INT,REG_FSP_INT_MASK);
FSP_WRITE_MASK(REG_FSP_CTRL,REG_FSP_2NDCMD_ON,REG_FSP_2NDCMD_MASK);
FSP_WRITE_MASK(REG_FSP_CTRL,REG_FSP_3THCMD_ON,REG_FSP_3THCMD_MASK);
FSP_WRITE_MASK(REG_FSP_CTRL,REG_FSP_3THCMD,REG_FSP_RDSR_MASK);
FSP_WRITE_MASK(REG_FSP_CTRL,REG_FSP_FSCHK_ON,REG_FSP_FSCHK_MASK);
FSP_WRITE_MASK(REG_FSP_TRIGGER,REG_FSP_FIRE,REG_FSP_TRIGGER_MASK);
bRet &= _HAL_FSP_WaitDone();
if(bRet == TRUE)
return 0;
return -2;
}
return -3;
}
二、普通写保护方式
设置状态寄存器的对应bit,一般flash末尾512k不保护,其他写保护,注意16Mflash和8Mflash对应的表不一样,调试过程中遇到过2个问题:
-
uboot中保护后,到kernel的flash驱动加载可能会取消保护的问题。
-
uboot和kernel中保护后,写、擦除flash导致状态寄存器的值被改写,保护被取消的问题。
//reg status1 bit6~bit2
//Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
//SRP0 BP4 BP3 BP2 BP1 BP0 WEL WIP //GD
//SRP SEC TB BP2 BP1 BP0 WEL BUSY //WINBOND
unsigned char SpiNor_ReadStatus1()
{
unsigned char ubStatus = 0;
SPI_Flash_Cmd(0x5, 1, &ubStatus, 1);
printf("SpiNor_ReadStatus1:0x%x\r\n", ubStatus);
return ubStatus;
}
unsigned char SpiNor_WriteStatus1(unsigned char ubStatus)
{
int ret = 0;
ret = SPI_Flash_Cmd(0x1, 0, &ubStatus, 1);
printf("SpiNor_WriteStatus1:0x%x, ret=%d\r\n", ubStatus, ret);
return ret;
}
unsigned char SpiNor_ReadStatus2()
{
unsigned char ubStatus = 0;
SPI_Flash_Cmd(0x35, 1, &ubStatus, 1);
printf("SpiNor_ReadStatus2:0x%x\r\n", ubStatus);
return ubStatus;
}
int SpiNor_WriteStatus2(unsigned char ubStatus)
{
int ret = 0;
ret = SPI_Flash_Cmd(0x31, 0, &ubStatus, 1);
printf("SpiNor_WriteStatus2:0x%x, ret=%d\r\n", ubStatus, ret);
return ret;
}
int SpiNor_Lock_Except_High512K(int bLock, int iCapMB)
{
int ret = 0;
unsigned char ubStatus = 0;
ubStatus = SpiNor_ReadStatus2();
if(!(ubStatus & (1<<6))) {
ubStatus |= (1<<6); //set CMP=1
ret = SpiNor_WriteStatus2(ubStatus);
}
//reg status1 bit6~bit2
//Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
//SRP0 BP4 BP3 BP2 BP1 BP0 WEL WIP //GD
//SRP SEC TB BP2 BP1 BP0 WEL BUSY //WINBOND
ubStatus = SpiNor_ReadStatus1();
if(bLock) {
ubStatus &= ~(0x3F<<2); //SRP SEC TB BP2 BP1 BP0 all=0
if(iCapMB == BYTES_8M) {
//SEC TB BP2 BP1 BP0
// 0 0 0 1 1
ubStatus |= 0x3<<2;
} else if(iCapMB == BYTES_16M) {
//SEC TB BP2 BP1 BP0
// 0 0 0 1 0
ubStatus |= 0x2<<2;
}
printf(">>unlock up 512k\n");
} else {
//unlock all
//SEC TB BP2 BP1 BP0
// x x 1 1 1
ubStatus &= ~(0x3F<<2);
ubStatus |= 0x7<<2; //lock none
printf(">>unlock all\n");
}
ret = SpiNor_WriteStatus1(ubStatus);
return ret;
}
int Flash_ProtectWhole(int bLockAll)
{
hal_SERFLASH_t *pFlashInfo = NULL;
unsigned char ubStatus = 0;
int ret = 0;
pFlashInfo = Get_SpiFlash_info();
if(pFlashInfo->u32FlashSize < BYTES_8M) {
printf("spi flash too small!\n");
return -1;
}
if(WinBand_Check_WPSBit()) {
//如果wps锁定,则先解锁wps
WinBand_Set_WPSBit(0);
WinBand_Set_GlobalLock(0);
}
ubStatus = SpiNor_ReadStatus2();
if(!(ubStatus & (1<<6))) {
ubStatus |= (1<<6); //set CMP=1
ret = SpiNor_WriteStatus2(ubStatus);
}
/* 锁定状态寄存器,需要重启后才能解锁
if(!(ubStatus & (1<<0))) {
ubStatus |= (1<<0); //set SRP1=1
ret = SpiNor_WriteStatus2(ubStatus);
}
*/
ubStatus = SpiNor_ReadStatus2();
printf("Flash_ProtectWhole FLAHS:pagesize:%d, cap:%d, CMP=%d, bLockAll=%d!\n", pFlashInfo->u32SecSize, pFlashInfo->u32FlashSize, !!(ubStatus&(1<<6)), bLockAll);
ubStatus = SpiNor_ReadStatus1();
ubStatus &= ~(0x3F<<2); //SRP SEC TB BP2 BP1 BP0 all=0
if(!bLockAll) {
//SEC TB BP2 BP1 BP0
// x x 1 1 1
ubStatus |= 0x7<<2; //lock none
printf(">>lock none\n");
} else {
//SEC TB BP2 BP1 BP0
// x x 0 0 0
//lock all
printf(">>lock all\n");
}
ret = SpiNor_WriteStatus1(ubStatus);
return ret;
}
int Flash_ProtectSomePart(int bLockEnv, int bOpEnvOnly)
{
//除最高512k外,全部写保护
//bLockEnv & bOpEnvOnly: not used for not wps mode
hal_SERFLASH_t *pFlashInfo = NULL;
unsigned char ubStatus = 0;
if(bOpEnvOnly) { //for test
ubStatus = SpiNor_ReadStatus2();
// 锁定状态寄存器,需要重启后才能解锁
if(!(ubStatus & (1<<0))) {
ubStatus |= (1<<0); //set SRP1=1
SpiNor_WriteStatus2(ubStatus);
}
return 0;
}
pFlashInfo = Get_SpiFlash_info();
if(pFlashInfo->u32FlashSize < BYTES_8M) {
printf("spi flash too small!\n");
return -1;
}
if(WinBand_Check_WPSBit()) {
//如果wps锁定,则先解锁wps
WinBand_Set_WPSBit(0);
WinBand_Set_GlobalLock(0);
}
ubStatus = SpiNor_ReadStatus2();
printf("Flash_ProtectSomePart FLAHS:pagesize:%d, cap:%d, CMP=%d!\n", pFlashInfo->u32SecSize, pFlashInfo->u32FlashSize, !!(ubStatus&(1<<6)));
}