📄 bootloader_atmega2560.c
字号:
boot_rww_enable(); // enable Read-While-Write section
address_page1 += SPM_PAGESIZE ;
}
address_flash += n_bytes ;
for(i = 0; i < MAX_BUF_SIZE; i++) {
rx_buffer[i] = 0xFF; // clear data buffer
}
msg_size = 2; // set message length
*(tx_pntr++) = CMD_PROGRAM_FLASH_ISP;
*(tx_pntr++) = STATUS_CMD_OK;
} // end of programFlashIsp
int main(void)
{
unsigned char rx_data; // received USART data byte
unsigned char state = STATE_READY; // actual state
initPorts();
bootCheck();
initUart();
//testCode();
for(;;)
{
rx_data=getch(); // get one byte from USART
msg_cs ^= rx_data;
switch( state ) {
// start processing when byte received
case STATE_READY :
if(rx_data == MESSAGE_START) // wait for message start
{
rx_pntr = &rx_buffer[0]; // reset pointer
msg_size = 0x00; // reset message size
state = STATE_GET_SEQ_NUM; // get sequence number next
}
else {
msg_cs = 0x00; // clear old checksum
#ifdef MONITOR
if ( rx_data == MONITOR_FLAG ) {
monitor_cnt ++;
if( monitor_cnt == 3 ) {
monitorMain();
}
}
else {
monitor_cnt = 0;
}
#endif
}
break;
// Get Sequence Number
case STATE_GET_SEQ_NUM :
sequence_number = rx_data; // store sequence number
state = STATE_GET_MSG_SIZE1; // get message size LSB next
break;
// Get Message Size 1
case STATE_GET_MSG_SIZE1:
msg_size = (((unsigned int)rx_data)<<8); // store message size MSB
state = STATE_GET_MSG_SIZE2; // get message size LSB next
break;
// Get Message Size 2
case STATE_GET_MSG_SIZE2:
msg_size += (unsigned int) rx_data; // make message size from MSB and LSB
// +1 because we check if >0
state = STATE_GET_TOKEN; // get token next
break;
// Get Token
case STATE_GET_TOKEN:
if(rx_data == TOKEN) // check if token is correct
state = STATE_GET_DATA; // get data next
else
state = STATE_READY; // wait for new message
break;
// Get Data
case STATE_GET_DATA:
*rx_pntr++ = rx_data;
--msg_size;
if(msg_size == 0)
{
state = STATE_GET_CS;
}
break;
// Get Checksum and handle message if correct
case STATE_GET_CS:
if( msg_cs == 0x00) { // check for valid checksum
handleMessage();
}
state = STATE_READY;
break;
}
} // end for endless loop
return 0; // main return value
} // end of main
/*----------------------------------------------------------------------------*/
/* Handle message */
/*----------------------------------------------------------------------------*/
void handleMessage(void) {
// new code begin
tx_pntr = &tx_buffer[0];
*(tx_pntr++) = MESSAGE_START ;
*(tx_pntr++) = sequence_number ;
tx_pntr += 2; // space reserved for message size
*(tx_pntr++) = TOKEN ;
rx_pntr = &rx_buffer[0]; // reset pointer
switch( *rx_pntr ) {
case CMD_SIGN_ON:
cmdSignOn();
break;
case CMD_GET_PARAMETER:
cmdGetParameter();
break;
case CMD_SET_PARAMETER:
cmdSetParameter();
break;
case CMD_ENTER_PROGMODE_ISP:
cmdEnterProgmodeIsp();
break;
case CMD_LEAVE_PROGMODE_ISP:
cmdLeaveProgmodeIsp();
break;
case CMD_CHIP_ERASE_ISP:
cmdChipEraseIsp();
break;
case CMD_READ_SIGNATURE_ISP:
cmdReadSignatureIsp();
break;
case CMD_LOAD_ADDRESS:
cmdLoadAddress();
break;
case CMD_PROGRAM_FLASH_ISP:
cmdProgramFlashIsp();
break;
case CMD_READ_FLASH_ISP:
cmdReadFlashIsp();
break;
case CMD_PROGRAM_EEPROM_ISP:
cmdProgramEepromIsp();
break;
case CMD_READ_EEPROM_ISP:
cmdReadEepromIsp();
break;
case CMD_READ_FUSE_ISP:
case CMD_READ_LOCK_ISP:
cmdReadFuseLockIsp();
break;
}
sendResponse();
// leave bootloader at programming end
/*
if( *answer_id_pntr == CMD_LEAVE_PROGMODE_ISP)
{
if(pgm_read_byte_near(0x0000) != 0xFF) {
app_start();
}
}
*/
} // end handleMessage
/*----------------------------------------------------------------------------*/
/* send response message */
/*----------------------------------------------------------------------------*/
void sendResponse(void) {
unsigned int msg_len, idx;
size_pntr[0] = (unsigned char) (msg_size >> 8);
size_pntr[1]= (unsigned char) (msg_size & 0xFF);
msg_len = tx_pntr - tx_buffer;
msg_cs = 0;
for( idx = 0; idx < msg_len; idx++ ) {
putch( tx_buffer[idx] );
msg_cs ^= tx_buffer[idx];
}
putch(msg_cs);
msg_cs = 0x00; // reset checksum
}
/*----------------------------------------------------------------------------*/
/* execute command CMD_SIGN_ON */
/*----------------------------------------------------------------------------*/
void cmdSignOn(void) {
msg_size = 11; // set message length
*(tx_pntr++) = CMD_SIGN_ON;
*(tx_pntr++) = STATUS_CMD_OK;
*(tx_pntr++) = 0x08; // send signature length
*(tx_pntr++) = 'S'; // send identifier
*(tx_pntr++) = 'T';
*(tx_pntr++) = 'K';
*(tx_pntr++) = '5';
*(tx_pntr++) = '0';
*(tx_pntr++) = '0';
*(tx_pntr++) = '_';
*(tx_pntr++) = '2';
}
/*----------------------------------------------------------------------------*/
/* execute command CMD_READ_SIGNATURE_ISP */
/*----------------------------------------------------------------------------*/
void cmdReadSignatureIsp(void) {
msg_size = 4; // set message length
*(tx_pntr++) = CMD_READ_SIGNATURE_ISP;
*(tx_pntr++) = STATUS_CMD_OK;
if( *(rx_pntr+4) == 0 ) { // 1st sig byte
*(tx_pntr++) = SIG1;
}
else if ( *(rx_pntr+4) == 1 ) { // 2nd sig byte
*(tx_pntr++) = SIG2;
}
else if ( *(rx_pntr+4) == 2 ) { // 3rd sig byte
*(tx_pntr++) = SIG3;
}
else {
*(tx_pntr++) = 0x00; // error
}
*(tx_pntr++) = STATUS_CMD_OK;
}
/*----------------------------------------------------------------------------*/
/* execute command CMD_SET_PARAMETER */
/*----------------------------------------------------------------------------*/
void cmdSetParameter(void) {
msg_size = 2; // set message length
*(tx_pntr++) = CMD_SET_PARAMETER;
*(tx_pntr++) = STATUS_CMD_OK;
}
/*----------------------------------------------------------------------------*/
/* execute command CMD_ENTER_PROGMODE_ISP */
/*----------------------------------------------------------------------------*/
void cmdEnterProgmodeIsp(void) {
msg_size = 2; // set message length
*(tx_pntr++) = CMD_ENTER_PROGMODE_ISP;
*(tx_pntr++) = STATUS_CMD_OK;
}
/*----------------------------------------------------------------------------*/
/* execute command CMD_LEAVE_PROGMODE_ISP */
/*----------------------------------------------------------------------------*/
void cmdLeaveProgmodeIsp(void) {
msg_size = 2; // set message length
*(tx_pntr++) = CMD_LEAVE_PROGMODE_ISP;
*(tx_pntr++) = STATUS_CMD_OK;
}
/*----------------------------------------------------------------------------*/
/* execute command CMD_CHIP_ERASE_ISP */
/*----------------------------------------------------------------------------*/
void cmdChipEraseIsp(void) {
// clear only first page becuase of timeout in AvrStudio
boot_page_erase((unsigned long)(0L)); // clear 1st page
while(boot_spm_busy());
boot_rww_enable(); // enable Read-While-Write section
msg_size = 2; // set message length
*(tx_pntr++) = CMD_CHIP_ERASE_ISP;
*(tx_pntr++) = STATUS_CMD_OK;
}
/*----------------------------------------------------------------------------*/
/* execute command CMD_LOAD_ADDRESS */
/*----------------------------------------------------------------------------*/
void cmdLoadAddress(void) {
address_eeprom = ((*(rx_pntr+3)*256)+*(rx_pntr+4));
address_flash = ((*(rx_pntr+3)*256)+*(rx_pntr+4))*2;
msg_size = 2; // set message length
*(tx_pntr++) = CMD_LOAD_ADDRESS;
*(tx_pntr++) = STATUS_CMD_OK;
}
/*----------------------------------------------------------------------------*/
/* execute command CMD_GET_PARAMETER */
/*----------------------------------------------------------------------------*/
void cmdGetParameter(void) {
msg_size = 3; // set message length
*(tx_pntr++) = CMD_GET_PARAMETER;
*(tx_pntr++) = STATUS_CMD_OK;
switch( *(rx_pntr+1) ) {
case PARAM_HW_VER:
*(tx_pntr++) = HARDWARE_VERSION; // send hardware version
break;
case PARAM_SW_MAJOR:
*(tx_pntr++) = SOFTWARE_MAJOR; // send software major version
break;
case PARAM_SW_MINOR:
*(tx_pntr++) = SOFTWARE_MINOR; // send software minor version
break;
case PARAM_VTARGET:
*(tx_pntr++) = VTARGET; // target supply voltage
break;
case PARAM_VADJUST:
*(tx_pntr++) = VADJUST; // target VREF voltage
break;
case PARAM_OSC_PSCALE:
*(tx_pntr++) = PSCALE_FSYS; // oscilator prescaler value
break;
case PARAM_OSC_CMATCH:
*(tx_pntr++) = CMATCH_DEF; // oscilator compare value
break;
case PARAM_SCK_DURATION:
*(tx_pntr++) = SCK_DURATION_DEF; // oscilator compare value
break;
#if defined(__AVR_ATmega128__) || defined(__AVR_AT90CAN128__) //|| defined(__AVR_ATmega2560__)
case PARAM_TOPCARD_DETECT:
*(tx_pntr++) = STK501; // STK501 is expected
break;
#endif
default:
*(tx_pntr++) = 0x00; // send dummy value for not supported parameters
break;
}
}
/*----------------------------------------------------------------------------*/
/* execute command CMD_PROGRAM_EEPROM_ISP */
/*----------------------------------------------------------------------------*/
void cmdProgramEepromIsp(void) {
n_bytes = ((*(rx_pntr+1)*256)+*(rx_pntr+2)); // number of databytes to flash
rx_pntr += 10; // set pointer to flash data
for( j = 0; j < n_bytes; j++ ) {
eeprom_wb(address_eeprom++,*(rx_pntr++));
}
for(i = 0; i < MAX_BUF_SIZE; i++) {
rx_buffer[i] = 0xFF; // clear data buffer
}
msg_size = 2; // set message length
*(tx_pntr++) = CMD_PROGRAM_EEPROM_ISP;
*(tx_pntr++) = STATUS_CMD_OK;
} // end of programEepromIsp
/*----------------------------------------------------------------------------*/
/* execute command CMD_READ_EEPROM_ISP */
/*----------------------------------------------------------------------------*/
void cmdReadEepromIsp(void) {
*(tx_pntr++) = CMD_READ_EEPROM_ISP;
*(tx_pntr++) = STATUS_CMD_OK;
n_bytes=((*(rx_pntr+1)*256)+*(rx_pntr+2)); // number of databytes to read from flash
for(i=0;i < n_bytes; i++) { // fill data buffer with n_bytes
*(tx_pntr++) = eeprom_rb( address_eeprom++ );
}
msg_size = n_bytes + 3; // set message length
*(tx_pntr++) = STATUS_CMD_OK;
} // end of readEepromIsp
/*----------------------------------------------------------------------------*/
/* set pin direction for bootloader pin and enable pullup */
/*----------------------------------------------------------------------------*/
void initPorts(void) {
#if defined(__AVR_ATmega128__) || defined(__AVR_AT90CAN128__)
BL_DDR &= ~(1 << BL0);
BL_DDR &= ~(1 << BL1);
BL_PORT |= (1 << BL0);
BL_PORT |= (1 << BL1);
#else
BL_DDR &= ~(1 << BL);
BL_PORT |= (1 << BL);
#endif
#ifdef MONITOR
#endif
}
/*----------------------------------------------------------------------------*/
/* initialize UART(s) depending on CPU defined */
/*----------------------------------------------------------------------------*/
void initUart(void) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -