📄 flash_drv_intel.c
字号:
};
const NOR_Die_Layout_S INTEL_W_B_32 = {
0x00400000,
{
{ 0x00000000, 8, 0x2000 }
,{ 0x00010000, 63, 0x10000 }
,{ 0, 0, 0 }
,{ 0, 0, 0 }
}
};
const NOR_Die_Layout_S INTEL_W_B_64 = {
0x00800000,
{
{ 0x00000000, 8, 0x2000 }
,{ 0x00010000, 127, 0x10000 }
,{ 0, 0, 0 }
,{ 0, 0, 0 }
}
};
const NOR_Die_Layout_S INTEL_W_B_128 = {
0x01000000,
{
{ 0x00000000, 8, 0x2000 }
,{ 0x00010000, 255, 0x10000 }
,{ 0, 0, 0 }
,{ 0, 0, 0 }
}
};
// W18/W30 series (Dual Boot)
const NOR_Die_Layout_S INTEL_W_TB_32 = {
0x00400000,
{
{ 0x00000000, 8, 0x2000 }
,{ 0x00010000, 62, 0x10000 }
,{ 0x003F0000, 8, 0x2000 }
,{ 0, 0, 0 }
}
};
const NOR_Die_Layout_S INTEL_W_TB_64 = {
0x00800000,
{
{ 0x00000000, 8, 0x2000 }
,{ 0x00010000, 126, 0x10000 }
,{ 0x007F0000, 8, 0x2000 }
,{ 0, 0, 0 }
}
};
const NOR_Die_Layout_S INTEL_W_TB_128 = {
0x01000000,
{
{ 0x00000000, 8, 0x2000 }
,{ 0x00010000, 254, 0x10000 }
,{ 0x00FF0000, 8, 0x2000 }
,{ 0, 0, 0 }
}
};
// Sibley series (pure 128KW sectors)
const NOR_Die_Layout_S INTEL_M18_128 = {
0x01000000,
{
{ 0x00000000, 64, 0x40000 }
,{ 0, 0, 0 }
,{ 0, 0, 0 }
,{ 0, 0, 0 }
}
};
const NOR_Die_Layout_S INTEL_M18_256 = {
0x02000000,
{
{ 0x00000000, 128, 0x40000 }
,{ 0, 0, 0 }
,{ 0, 0, 0 }
,{ 0, 0, 0 }
}
};
const NOR_Die_Layout_S INTEL_M18_512 = {
0x04000000,
{
{ 0x00000000, 256, 0x40000 }
,{ 0, 0, 0 }
,{ 0, 0, 0 }
,{ 0, 0, 0 }
}
};
//------------------------------------------------------------------------------
// Check Device ID Callback Function
//------------------------------------------------------------------------------
bool INTEL_CheckDevID(const uint16 dev, volatile uint16 *die1_addr, volatile uint16 *die2_addr) {
uint16 die1_manufacture_code;
uint16 die1_dev_code;
uint16 die2_manufacture_code;
uint16 die2_dev_code;
uint16 die_count = 0;
bool ret;
// clear status register first
die1_addr[0x0] = INTEL_CMD_CLR_SR;
// issue device id command
die1_addr[0x0] = INTEL_CMD_READ_ID;
// read manufacture id and device code
die1_manufacture_code = die1_addr[0x0];
die1_dev_code = die1_addr[0x01];
// compare id
if( g_FlashDevTbl[dev].m_hw_info.m_manufacture_code != die1_manufacture_code )
goto not_match;
// if manufacture code exist, temporarily record flash id to g_HW_DetectionResult
g_HW_DetectionResult.m_flash_dev_code_1 = die1_manufacture_code;
g_HW_DetectionResult.m_flash_dev_code_2 = die1_dev_code;
if( g_FlashDevTbl[dev].m_hw_info.m_dev_code != die1_dev_code )
goto not_match;
// die1 id matched, continue to check if this flash is dual stack
if( 0 != memcmp((void *)die1_addr, (void *)die2_addr, 64) ) {
// if it's dual stack, the 2nd die baseaddr won't enter auto-select mode,
// the data locate in die1 and die2 address won't be the same.
die_count = 2;
}
else {
// otherwise the 2nd baseaddr will enter auto-select mode due to address wrap,
// the data locate in die1 and die2 address will be the same.
die_count = 1;
}
// if die count matched, return true
if( die_count == FLASH_DIE_COUNT(dev) ) {
// compare die2 id
if( (2 == FLASH_DIE_COUNT(dev)) &&
(0 != g_FlashDevTbl[dev].m_hw_info.m_ext_dev_code1) &&
(0 != g_FlashDevTbl[dev].m_hw_info.m_ext_dev_code2)
) {
// clear status register first
die2_addr[0x0] = INTEL_CMD_CLR_SR;
// issue device id command
die2_addr[0x0] = INTEL_CMD_READ_ID;
// read manufacture id and device code
die2_manufacture_code = die2_addr[0x0];
die2_dev_code = die2_addr[0x01];
// compare id
if( g_FlashDevTbl[dev].m_hw_info.m_ext_dev_code1 != die2_manufacture_code )
goto not_match;
// if manufacture code exist, temporarily record flash id to g_HW_DetectionResult
g_HW_DetectionResult.m_flash_dev_code_3 = die2_manufacture_code;
g_HW_DetectionResult.m_flash_dev_code_4 = die2_dev_code;
if( g_FlashDevTbl[dev].m_hw_info.m_ext_dev_code2 != die2_dev_code )
goto not_match;
}
// found
goto match;
}
not_match:
ret = FALSE;
goto end;
match:
ret = TRUE;
end:
// reset die1 to read mode
die1_addr[0x0] = INTEL_CMD_READ_ARRAY;
// reset die2 to read mode
die2_addr[0x0] = INTEL_CMD_READ_ARRAY;
return ret;
}
//------------------------------------------------------------------------------
// Check If Device Is Idle Callback Function
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Erase Related Callback Function
//------------------------------------------------------------------------------
void INTEL_Erase_Block_CMD(const uint32 blockaddr)
{
volatile uint16 *ba = (volatile uint16 *)blockaddr;
// clear status register first
ba[0x0] = INTEL_CMD_CLR_SR;
// unlock block first
ba[0x0] = INTEL_CMD_SW_UNLOCK_STEP1;
ba[0x0] = INTEL_CMD_SW_UNLOCK_STEP2;
// erase
ba[0x0] = INTEL_CMD_ERASE_STEP1;
ba[0x0] = INTEL_CMD_ERASE_STEP2;
}
STATUS_E INTEL_Erase_CheckDone(const uint32 blockaddr)
{
volatile uint16 *ba = (volatile uint16 *)blockaddr;
volatile uint16 sr;
// read SR
ba[0x0] = INTEL_CMD_READ_SR;
sr = *ba;
if( !(sr&INTEL_SR7_DWS_BIT) ) {
return S_IN_PROGRESS;
}
else if(sr&INTEL_SR3_VPPS_BIT) {
return S_VPP_RANGE_ERR;
}
else if( (sr&INTEL_SR4_PS_BIT) && (sr&INTEL_SR5_ES_BIT) ) {
return S_CMD_ERR;
}
else if(sr&INTEL_SR5_ES_BIT) {
return S_ERASE_FAILED;
}
else if(sr&INTEL_SR1_BLS_BIT) {
return S_BLOCK_LOCKED_ERR;
}
// reset to read mode
ba[0x0] = INTEL_CMD_READ_ARRAY;
return S_DONE;
}
//------------------------------------------------------------------------------
// Program Related Callback Function
//------------------------------------------------------------------------------
void INTEL_PreProcess_32WORD_BUFPGM(const uint16 dev) {
// set max buffered program size
g_FLASH_MAX_BUFPGM_SIZE_IN_BYTE = 64; // 32 WORDs
}
void INTEL_Block_Unlock(const uint32 blockaddr)
{
volatile uint16 *ba = (volatile uint16 *)blockaddr;
// clear status register first
ba[0x0] = INTEL_CMD_CLR_SR;
// unlock
ba[0x0] = INTEL_CMD_SW_UNLOCK_STEP1;
ba[0x0] = INTEL_CMD_SW_UNLOCK_STEP2;
// reset to read mode
ba[0x0] = INTEL_CMD_READ_ARRAY;
}
void INTEL_Word_Program(const uint32 blockaddr, const uint32 prog_addr, const uint16 data)
{
volatile uint16 *pa = (volatile uint16 *)prog_addr;
// clear status register first
*pa = INTEL_CMD_CLR_SR;
// word program
*pa = INTEL_CMD_WORD_PGM;
*pa = data;
}
STATUS_E INTEL_Word_Program_CheckDone(const uint32 prog_addr)
{
volatile uint16 *pa = (volatile uint16 *)prog_addr;
volatile uint16 sr;
// read SR
*pa = INTEL_CMD_READ_SR;
sr = *pa;
if( !(sr&INTEL_SR7_DWS_BIT) ) {
return S_IN_PROGRESS;
}
else if(sr&INTEL_SR3_VPPS_BIT) {
return S_VPP_RANGE_ERR;
}
else if(sr&INTEL_SR4_PS_BIT) {
return S_PGM_FAILED;
}
else if(sr&INTEL_SR1_BLS_BIT) {
return S_BLOCK_LOCKED_ERR;
}
// reset to read mode
*pa = INTEL_CMD_READ_ARRAY;
return S_DONE;
}
void INTEL_Buf_Program(const uint32 blockaddr, const uint32 prog_addr, const uint16 *data, const uint32 length_in_word)
{
//
// Be careful!! Before you invoke this function, you must calculate a reasonable
// length_in_word and make sure the program data won't exceed the sector boundary.
//
volatile uint16 *pa = (volatile uint16 *)prog_addr;
uint32 i;
// clear status register first
*pa = INTEL_CMD_CLR_SR;
// enter buffered programming
*pa = INTEL_CMD_BUF_PGM;
// set data count
*pa = length_in_word-1;
for(i=0; i<length_in_word; i++) {
// fill data to device buffer
pa[i] = data[i];
}
// set confirm command to flush buffer to flash
*pa = INTEL_CMD_BUF_PGM_CNF;
}
//------------------------------------------------------------------------------
// Sibley Related Callback Function
//------------------------------------------------------------------------------
void INTEL_Sibley_PreProcess_1KB_BUFPGM(const uint16 dev) {
// set max buffered program size
g_FLASH_MAX_BUFPGM_SIZE_IN_BYTE = INTEL_SIBLEY_PGM_REGION_SIZE_IN_BYTE; // 1KB
}
STATUS_E INTEL_Sibley_Program_CheckDone(const uint32 prog_addr)
{
volatile uint16 *pa = (volatile uint16 *)prog_addr;
volatile uint16 sr;
// read SR
*pa = INTEL_CMD_READ_SR;
sr = *pa;
if( !(sr&INTEL_SR7_DWS_BIT) ) {
return S_IN_PROGRESS;
}
else if(sr&INTEL_SR3_VPPS_BIT) {
return S_VPP_RANGE_ERR;
}
else if(sr&INTEL_SR4_PS_BIT) {
switch(sr&INTEL_RPS_MASK) {
case INTEL_RPS_REWRITE_OBJ_MODE_REGION:
return S_SIBLEY_REWRITE_OBJ_MODE_REGION;
case INTEL_RPS_WRITE_B_HALF_IN_CTRL_MODE_REGION:
return S_SIBLEY_WRITE_B_HALF_IN_CTRL_MODE_REGION;
case INTEL_RPS_ILLEGAL_CMD:
return S_SIBLEY_ILLEGAL_CMD;
default:
return S_PGM_FAILED;
}
}
else if(sr&INTEL_SR1_BLS_BIT) {
return S_BLOCK_LOCKED_ERR;
}
// reset to read mode
*pa = INTEL_CMD_READ_ARRAY;
return S_DONE;
}
void INTEL_Sibley_Buf_Program(const uint32 blockaddr, const uint32 prog_addr, const uint16 *data, const uint32 length_in_word)
{
//
// Be careful!! Before you invoke this function, you must calculate a reasonable
// length_in_word and make sure the program data won't exceed the sector boundary.
//
volatile uint16 *pa = (volatile uint16 *)prog_addr;
uint32 i;
// clear status register first
*pa = INTEL_CMD_CLR_SR;
// enter buffered programming
*pa = INTEL_CMD_SIBLEY_BUF_PGM;
// set data count
*pa = length_in_word-1;
for(i=0; i<length_in_word; i++) {
// fill data to device buffer
pa[i] = data[i];
}
// set confirm command to flush buffer to flash
*pa = INTEL_CMD_BUF_PGM_CNF;
}
//------------------------------------------------------------------------------
// Protection Related Callback Function
//------------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -