spi nor flash写保护

该文详细介绍了如何使用WPS位和全局/局部块锁来保护SPI闪存,包括设置和解除保护的函数实现。此外,还讨论了普通写保护方式,通过修改状态寄存器实现对特定区域的保护策略,特别提到了不同容量的Flash配置差异以及可能遇到的问题。
摘要由CSDN通过智能技术生成

一、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个问题:

  1. uboot中保护后,到kernel的flash驱动加载可能会取消保护的问题。

  2. 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)));
	
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值