📄 mbusman.cpp
字号:
/**
* CAT24C021: write several bytes( less than or equal to 16 bytes).
*
* @param baseAddr the first address
* @param byteNum the number of bytes to be written
* @param data point to what to write
*
* @return 1 if the operation succeed.
* 0 if the operation failure because packetQue is full.
*/
CHAR CAT24C021WritePage(UINT16 baseAddr, UINT16 byteNum, UCHAR *data)
{
MBusPackType thePack;
UCHAR sect_addr;
CHAR i;
// one page has less than 16 bytes
if ( 1 > byteNum || CAT24C021_PAGE_SIZE < byteNum)
return 0;
thePack.txLen1 = 2 + byteNum;
thePack.txLen2 = 0;
thePack.rxLen = 0;
thePack.repeatTimes = CAT24C021_WRITE_REPEAT;
// The bit8 and bit9 of baseaddr must put in slave address
// a sector has 256 bytes, so the following operation will
// save the bit8 and bit9 in sect_addr
sect_addr = baseAddr >> 8;
sect_addr = sect_addr << 1;
thePack.txData[0] = CAT24C021_SLAVE_ADDR | sect_addr | OP_WRITE;
thePack.txData[1] = (baseAddr & 0xff);
for (i = 0; i < byteNum; i ++)
thePack.txData[2+i] = *data ++;
/*
if (OPMODE_INTERRUPT == sMBusInfo.mode)
{
if (1 == MBusPackQuePut(&gCAT24C021WritePackQue, &thePack))
{
EnterInterrupt( );
return 1;
}
return 0;
}
else
*/
return MBusTransferByQuery(&thePack);
}
/**
* CAT24C021: write several bytes( no limitation to the number).
*
* @param baseAddr the first address
* @param byteNum the number of bytes to be written
* @param data point to what to write
*
* @return 1 if the operation succeed.
* 0 if the operation failure because packetQue is full
* or byteNum is improper.
*/
CHAR CAT24C021WriteSeqByte(UINT16 baseAddr, UINT16 byteNum, UCHAR *data)
{
UCHAR i;
if (1 > byteNum || 2048 < (baseAddr + byteNum) )
return 0;
// write the first bytes of one page.
i = CAT24C021_PAGE_SIZE - ( baseAddr % CAT24C021_PAGE_SIZE );
if (i > byteNum)
i = byteNum;
if (0 == CAT24C021WritePage(baseAddr, i, data) )
return 0;
baseAddr += i;
data += i;
byteNum -= i;
// transfer data page by page
while (CAT24C021_PAGE_SIZE <= byteNum)
{
if (0 == CAT24C021WritePage(baseAddr, CAT24C021_PAGE_SIZE, data) )
return 0;
baseAddr += CAT24C021_PAGE_SIZE;
data += CAT24C021_PAGE_SIZE;
byteNum -= CAT24C021_PAGE_SIZE;
}
// transfer the remained data.
if (0 < byteNum)
return CAT24C021WritePage(baseAddr, byteNum, data);
else
return 1;
}
/**
* CAT24C021: read several bytes.
*
* @param baseAddr the first byte address
* @param byteNum the number of bytes to be read
* @param dataAddr where to store result
*
* @return 1 if the operation succeed.
* 0 if the operation failure because packetQue is full
* or byteNum is improper.
* @note A NU_Sleep will be called if MBUS operated in interupt mode.
*/
CHAR CAT24C021ReadSeqByte(UINT16 baseAddr, UINT16 byteNum, UCHAR *dataAddr)
{
MBusPackType thePack;
UCHAR sect_addr;
int k;
if (1 > byteNum || 2048 < (baseAddr + byteNum) )
return 0;
thePack.txLen1 = 2;
thePack.txLen2 = 1;
thePack.rxLen = byteNum;
thePack.rxData = dataAddr;
thePack.repeatTimes = CAT24C021_READ_REPEAT;
// The bit8 and bit9 of baseaddr must put in slave address
// a sector has 256 bytes, so the following operation will
// save the bit8 and bit9 in sect_addr
sect_addr = baseAddr >> 8;
sect_addr = sect_addr << 1;
thePack.txData[0] = CAT24C021_SLAVE_ADDR | sect_addr | OP_WRITE;
thePack.txData[1] = (baseAddr & 0xff);
thePack.txData[2] = CAT24C021_SLAVE_ADDR | sect_addr | OP_READ;
/*
if (OPMODE_INTERRUPT == sMBusInfo.mode)
{
if (1 == MBusPackQuePut(&gCAT24C021ReadPackQue, &thePack))
{
EnterInterrupt( );
// Important changing: LLH.2001.07.04
// A Sleep added here to wait for the data trasnferring been done,
// so, after returning from this function, you can use data be read
// immedidately.
//NU_Sleep( 50);
k = 0;
while( k < 50000 )
k++;
return 1;
}
return 0;
}
else
*/
return MBusTransferByQuery(&thePack);
}
/**
* Reset watchdog. the command sequence of CAT24C021(reading current byte)
* is used here.
*
* @note CAT24C021 has a watchdog, which will reset CPU every 1.6 seconds
* if no MBUS operation occurred in this period.
*/
// CHAR CAT24C021ReadCurrentByte(UCHAR *dataAddr)
VOID ResetWatchdog( VOID )
{
static UCHAR data;
MBusPackType thePack;
thePack.txLen1 = 1;
thePack.txLen2 = 0;
thePack.rxLen = 1;
thePack.rxData = &data;
thePack.repeatTimes = 0;
thePack.txData[0] = CAT24C021_SLAVE_ADDR | OP_READ;
/*
if (OPMODE_INTERRUPT == sMBusInfo.mode)
{
if (1 == MBusPackQuePut(&gCAT24C021ReadPackQue, &thePack))
EnterInterrupt( );
}
else
*/
MBusTransferByQuery(&thePack);
}
/**
* MBUS: Transfer a packet by query.
*
* @param thePack the packet to be transfered
*
* @return 1 if the operation succeed.
* 0 if the operation failure because packetQue is full.
*/
static CHAR MBusTransferByQuery(MBusPackType *thePack)
{
// if MBUS working not in query mode, return
if (OPMODE_QUERY != sMBusInfo.mode)
return 0;
// Don't goto the following code if there another task using it.
// use the statement to protect the following code being used exclusively.
if (1 != sMBusInfo.currPackFinished)
return 0;
// packet has not been transfered
sMBusInfo.currPackFinished = 0;
// Remember the pack being transfered.
sMBusInfo.currPack = *thePack;
// construct command sequence
ConstructSequence(thePack);
// if MBUS is not free until function return, transfer stop
if (0 == WaitForMBusFree())
{
sMBusInfo.currPackFinished = 1;
return 0;
}
StartTransfer();
do
{
// if MIF has not been set until function return, transfer stop
if (0 == WaitForMIF())
{
sMBusInfo.currPackFinished = 1;
return 0;
}
// currPackFinished will be set to 1 if the packet transfered in MBusLisr
Mbus_Lisr(0);
}while (0 == sMBusInfo.currPackFinished);
return 1;
}
/**
* Wait for some times until MBUS is not busy.
*
* @return 1 if MBUS is free when returned.
* 0 MBUS is still busy until return
*/
static UCHAR WaitForMBusFree(VOID)
{
UCHAR status;
UINT16 i;
// wait for 500 loops
for (i = 0; i < 500; i ++)
{
status = *(UCHAR*)MBSR;
if (0 == (status&0x20))
return 1;
}
return 0;
}
/**
* Wait for some times until MBUS Interrupt is set, which indicate that a data
* transfer is completed.
*
* @return 1 if MBUS is free when returned.
* 0 MBUS is still busy until return
*/
static UCHAR WaitForMIF(VOID)
{
UCHAR status;
UINT16 i;
// wait for 500 loops
for (i = 0; i < 500; i ++)
{
status = *(UCHAR*)MBSR;
if (2 == (status&2))
return 1;
}
return 0;
}
/**
* CAT24C021: Calculate checksum and write it to memory.
*
* @param baseAddr the first address
* @param byteNum the number of bytes to be written
* @param data point to what to write
*
* @return 1 if the operation succeed.
* 0 if the operation failure because packetQue is full.
*
* @note the sCheckSum must been calculated when sMemoryMap loaded
*
static VOID UpdateCheckSum(UINT16 baseAddr, UINT16 byteNum, UCHAR *data)
{
INT16 i;
INT16 index;
index = baseAddr;
for (i = 0; i < byteNum; i ++)
{
sCheckSum -= sMemoryMap[index];
sCheckSum += *data;
sMemoryMap[index++] = *data ++;
}
CAT24C021WriteSeqByte(MAP_CHECK_SUM, 1, &sCheckSum);
}
/**
* CAT24C021: Load the EEPROM to make a copy in DRAM and check the checkSum.
* this function must be called before any writing operation to CAT24C021
* with checkSum, or the check sum will be wrong.
*
* @param memoryMap where to save the copy
*
* @return 1 load memoryMap and stored checkSum succeeded and checkSum is right
* 0 load memoryMap or stored checkSum failed
* 2 load memoryMap and stored checkSum succeeded but checkSum is wrong
*
static CHAR CAT24C021LoadMemoryMap(UCHAR *memoryMap)
{
UCHAR storedCheckSum;
INT16 i;
INT eeprom_size = EEPROM_SIZE;
// if MBUS working not in query mode, return
if (OPMODE_QUERY != sMBusInfo.mode)
return 0;
// Read memory map, 512 bytes at one time reading
for (i = 0; i < eeprom_size / 512; i ++)
{
if ( 0 == CAT24C021ReadSeqByte( i * 512, 512, memoryMap + i * 512) )
return 0;
}
if ( 0 != (eeprom_size%512) )
if ( 0 == CAT24C021ReadSeqByte( i * 512, eeprom_size%512, memoryMap + i * 512) )
return 0;
// Read stored checkSum
if ( 0 == CAT24C021ReadSeqByte( MAP_CHECK_SUM, 1, &storedCheckSum) )
return 0;
// Calculate checksum
sCheckSum = 0;
for (i = MAP_SYS_KEYVOL_LEAD_LANG_ARR; i < MAP_CHECK_SUM; i++)
sCheckSum += sMemoryMap[i];
if (sCheckSum != storedCheckSum)
return 2;
else
return 1;
}
/**
* The copy of CAT24C021WritePage with checksum calculating and writing
*
* @see CAT24C021WritePage
*
CHAR CAT24C021WritePageWithCheck(UINT16 baseAddr, UINT16 byteNum, UCHAR *data)
{
if (CAT24C021WritePage(baseAddr, byteNum, data))
{
UpdateCheckSum(baseAddr, byteNum, data);
return 1;
}
else
return 0;
}
/**
* The copy of CAT24C021WriteSeqByte with checksum calculating and writing
*
* @see CAT24C021WriteSeqByte
*
CHAR CAT24C021WriteSeqByteWithCheck(UINT16 baseAddr, UINT16 byteNum, UCHAR *data)
{
if (CAT24C021WriteSeqByte(baseAddr, byteNum, data))
{
UpdateCheckSum(baseAddr, byteNum, data);
return 1;
}
else
return 0;
}
/**
* Whether MBUS is work in query mode.
*
* @return 1 if work in query mode
* 0 if not in query mode
*/
INT IsMBusInQueryMode( VOID )
{
if (OPMODE_QUERY == sMBusInfo.mode)
return 1;
else
return 0;
}
/*
CHAR* GetMBusRegisters( VOID )
{
static CHAR sStatusString[100];
sprintf( sStatusString,
"MADR:%02x, MFDR:%02x, MBCR:%02x, MBSR:%02x, MBDR:%02x, MBUS_ICR:%02x",
*(UCHAR*)MADR, *(UCHAR*)MFDR, *(UCHAR*)MBCR,
*(UCHAR*)MBSR, *(UCHAR*)MBDR, *(UCHAR*)MBUS_ICR );
return sStatusString;
}*/
VOID ReInitializeMBus( VOID )
{
if (OPMODE_QUERY == sMBusInfo.mode)
MBusInit( );
else
{
MBusInit( );
}
}
#define EEPROM_RETRY_NUM 10
BOOL WriteEeprom(UINT32 addr, UINT32 count, UCHAR* data)
{
UCHAR temp_data[EEPROM_SIZE];
int i;
for (i = 0; i < EEPROM_RETRY_NUM; i++ )
{
CAT24C021WriteSeqByte(addr, count, data);
for (int j = 0; j < 1000; j++ )
;
CAT24C021ReadSeqByte(addr, count, temp_data);
if ( 0 == memcmp(temp_data, data, count))
break;
}
if (i == EEPROM_RETRY_NUM)
{
return FALSE;
}
else
{
return TRUE;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -