📄 bootloader_smbus.c
字号:
void EEwrite(unsigned int address, unsigned char data)
{
while(EECR & (1<<EEPE));
EEAR = address;
EEDR = data;
EECR = (1<<EEMPE); //do an Erase and a Write
EECR = (1<<EEMPE) | (1<<EEPE);
}
void LoopMemory(void)
{
if(LoopFlag == 'E') //this indicates "Write to EEPROM"
{
if(EEbusy())
return;
EEwrite(eptr++, SRAMbuffer[dest_i++]);
if(--ctr)
return;
Status = SUCCESS;
LoopFlag = 0;
return;
}
else
if(LoopFlag == 'e') //this indicates "Erase EEPROM"
{
if(EEbusy())
return;
EEerase(eptr++);
if(--ctr)
return;
Status = SUCCESS;
LoopFlag = 0;
return;
}
}
//This function interprets received commands.
void SMB_CmdInterpreter(void)
{
unsigned char temp;
if(UsePEC) //check the CRC of the received packet.
{
temp = 0; //use this as our CRC value.
do { temp = FastCRC(temp, TW_RxBuf[TW_RxBufIndex++]); }
while(TW_RxBufCnt != TW_RxBufIndex);
if(temp) //The result of a CRC check SHOULD be =0 if all was ok.
{
Status = CRCERROR;
TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN); //have TWI continue from where it stalled.
return;
}
}
// Message is valid enough to warrant calling each command's handler now.
Status = BUSY; //in case it's a "looped" operation...
if(!BigData)
{
// TW_RxBufIndex = 3; //point to the first byte of Received Data.
lomemptr = TW_RxBuf[TWRX_LOADDR];
himemptr = TW_RxBuf[TWRX_HIADDR];
src_i = TWRX_DATA;
dest_i = TW_RxBuf[TWRX_OFFSET];
ctr = TW_RxBuf[TWRX_SIZE];
temp = TW_RxBuf[TWRX_CMD]; //What is the command?
}
else
{
temp = 'I';
src_i = 3; //for all follow-on blocks, data MUST start at 3!
//Note that ctr and dest_i are still valid from the previous block.
}
if(temp == 'W') //Write SRAMbuffer data into memory
{
if(TW_RxBuf[TWRX_MEM] == 'F') //flash?
{
src_i = 0; //index into SRAMbuffer
lomemptr &= 0x80; //make sure the page boundary is clean
dest_i = lomemptr;
do
{
#pragma diag_suppress=Pe1053 // Suppress warning for conversion from long-type address to flash ptr.
_FILL_TEMP_WORD(((himemptr<<8)|dest_i), (SRAMbuffer[src_i]|(SRAMbuffer[src_i+1]<<8)));
#pragma diag_default=Pe1053 // Back to default.
src_i += 2; // Select next word from SRAMbuffer.
dest_i += 2; // Update flash page pointer.
}
while(src_i < 0x80); // Loop until all bytes written.
_PAGE_WRITE((himemptr<<8)|lomemptr);
_WAIT_FOR_SPM();
_ENABLE_RWW_SECTION();
Status = SUCCESS;
}
else
if(TW_RxBuf[TWRX_MEM] == 'E') //eeprom?
{
eptr = (himemptr<<8) | lomemptr;
if((eptr + ctr) > 512)
Status = BADPARAM;
else
{
LoopFlag = 'E'; //this indicates "Write to EEPROM"
}
}
else
Status = BADPARAM;
}
else
if(temp == 'V') //Verify info in SRAMbuffer against memory
{
if(TW_RxBuf[TWRX_MEM] == 'F') //flash?
{
src_i = SUCCESS; //use this variable to hold status
dest_i = 0;
fptr = (unsigned char __flash *)(lomemptr | (himemptr<<8));
do { if(SRAMbuffer[dest_i++] != *fptr++) src_i=FAILURE; }
while (dest_i < 128);
Status = src_i;
}
else
if(TW_RxBuf[TWRX_MEM] == 'E') //eeprom?
{
eptr = (himemptr<<8) | lomemptr;
if((eptr + ctr) > 512)
Status = BADPARAM;
else
{
src_i = SUCCESS; //use this variable to hold status
do { if(SRAMbuffer[dest_i++] != EEget(eptr++)) src_i=FAILURE; }
while (--ctr);
Status = src_i;
}
}
else
Status = BADPARAM;
}
else
if(temp == 'E') //Erase memory, starting at the specified address
{
if(TW_RxBuf[TWRX_MEM] == 'F') //flash?
{
_WAIT_FOR_SPM();
#pragma diag_suppress=Pe1053 // Suppress warning for conversion from long-type address to flash ptr.
_PAGE_ERASE( (himemptr<<8) | (lomemptr & 0x80) );
#pragma diag_default=Pe1053 // Back to default.
Status = SUCCESS;
}
else
if(TW_RxBuf[TWRX_MEM] == 'E') //eeprom?
{
eptr = (himemptr<<8) | lomemptr;
if((eptr + ctr) > 512)
Status = BADPARAM;
else
{
LoopFlag = 'e'; //this indicates "erase EEPROM"
}
}
else
Status = BADPARAM;
}
else
if(temp == 'P') //prepare to Patch a block of memory by reading it into SRAMbuffer
{
if(TW_RxBuf[TWRX_MEM] == 'F') //flash?
{
if(lomemptr & 0x7F) //it must be on a page boundary!!
Status = BADPARAM;
else
{
dest_i = 0;
fptr = (unsigned char __flash *)(lomemptr | (himemptr<<8));
do {SRAMbuffer[dest_i++] = *fptr++; }
while (dest_i < 128);
Status = SUCCESS;
}
}
else
if(TW_RxBuf[TWRX_MEM] == 'E') //eeprom?
{
eptr = (himemptr<<8) | lomemptr;
if((eptr + ctr) > 512)
Status = BADPARAM;
else
{
do { SRAMbuffer[dest_i++] = EEget(eptr++); }
while (--ctr);
Status = SUCCESS;
}
}
else
Status = BADPARAM;
}
else
if(temp == 'A') //Activate BootLoader ISP code (ignored in this code)
{
Status = SUCCESS; //no action required, just ignore
}
else
if(temp == 'I') //Insert data from this packet into SRAMbuffer at the offset specified
{
if((ctr+dest_i) > 128)
Status = BADPARAM;
else
{
if(!BigData)
{
if(ctr > 26) //26 is the most that can fit in an initial packet
{
BigData = 1;
temp = TW_RxBuf[TWRX_BLKCNT] - 6;
}
else
temp = ctr;
}
else //this is a chained packet and MAY contain up to 32 bytes of data.
{
if(ctr <= TW_RxBuf[TWRX_BLKCNT])
BigData = 0;
temp = TW_RxBuf[TWRX_BLKCNT];
}
do
{
SRAMbuffer[dest_i++] = TW_RxBuf[src_i++];
ctr--;
}
while (--temp);
Status = SUCCESS;
}
}
else
if(temp == 'w') //first decrypt the entire SRAM block, THEN write.
{
; //! \todo Add code here if encryption is desired.
}
else
if(temp == 'v') //first decrypt the entire SRAM block, THEN verify.
{
; //! \todo Add code here if encryption is desired.
}
else
if(temp == 'X') //Exit the BootLoader
{
asm("jmp 0");
}
else //Not a valid command from our list
{
SMB_BusTimeout(); //Generate a bus timeout.
TW_RxBufIndex = 0; //Wipe out anything in the buffer, just in case.
TW_RxBufCnt = 0;
return;
}
//At this point it looks like everything went OK.
TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN); //have TWI continue from where it stalled.
return;
}
//This function restores the SMBus & the TWI_ISR state machine to normal after
// we have deliberately generated a bus timeout error (in order to tell the
// Master that something was wrong with his last command).
void SMB_RestoreBus(void)
{
TWCR = 0; //shut down the peripheral
TW_state = TW_IDLE; //force an init of the state machine
TWAR = 0x16;
TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN); // | (1<<TWSTO) re-enable
//Note that we must be careful not to generate some kind of bus error
// as a result of waking back up, or we will get into an endless loop
// by generating another bus timeout if the IDLE state doesn't like
// something it sees when it comes back to life.
}
/* *************************************************************************
*
* Utilities for SMBus commmunications
*
************************************************************************* */
__flash unsigned char crctable[16] = {0,0x07,0x0E,0x90, 0x1c,0x1b,0x12,0x15, 0x38,0x3F,0x36,0x31, 0x24,0x23,0x2A,0x2D};
__flash unsigned char crctable2[16] = {0,0x70,0xE0,0x90, 0xC1,0xB1,0x21,0x51, 0x83,0xF3,0x63,0x13, 0x42,0x32,0xA2,0xD2};
unsigned char FastCRC(unsigned char LastCRC, unsigned char newbyte)
{
unsigned char index;
index = newbyte;
index ^= LastCRC;
index >>= 4;
LastCRC &= 0x0F;
LastCRC ^= crctable2[index];
index = LastCRC;
index ^= newbyte;
index &= 0x0F;
LastCRC &= 0xF0;
LastCRC ^= crctable[index];
return(LastCRC);
}
/* This version doesn't require crctable2[], but requires more shifts.
unsigned char SlowerCRC(unsigned char LastCRC, unsigned char newbyte)
{
unsigned char index;
index = newbyte;
index ^= LastCRC;
index >>= 4;
LastCRC <<= 4;
LastCRC ^= crctable[index];
index = LastCRC >> 4;
index ^= newbyte;
index &= 0x0F;
LastCRC <<= 4;
LastCRC ^= crctable[index];
return(LastCRC);
} */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -