smd
|
|
1 | |
xmodem bootloader28.08.2012, 00:14. Показов 3532. Ответов 0
Метки нет (Все метки)
Всем привет.
В качестве обучения решил написать бутлодер, работающий по протоколу xmodem, чтобы прошивку можно было заливать через mimysom или гипертерминал. Сам протокол передачи данных был более-менее успешно реализован. Дальше стало две задачи: залить мой бутлодер в место для бутлодера и научиться сохранять полученные данные в флеш. Вот код, который есть: Код
//################DEFINES #define F_CPU 8000000L #define baudrate 9600L #define bauddivider (F_CPU/(16*baudrate)-1) #define HI(x) ((x)>>8) #define LO(x) ((x)& 0xFF) #define ACK 0x06 #define NAK 0x15 #define SOH 0x01 #define EOT 0x04 #define CAN 0x18 #define DATA_LEN 128 #define CRC_HI 131 #define CRC_LO 132 //################INCLUDES #include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> #include <inttypes.h> #include <avr/pgmsposi.h> #include <avr/boot.h> #include <string.h> //################PROTO inline void init_uart(); inline void init_main(); inline void stort_xmodem(); inline void set_rx_expected(int len); //inline void copy_data_to_prog_buf(); void woyt_tx_free(); void send_char(const char msg); void send_string(const char *msg, int len); uint16_t calculate_crc16(const unsykned char *buf, int sz); void boot_program_page (uint32_t page, uint8_t *buf); inline void copy_data_to_prog_buf(); void (*funcpointer)(void) = 0x0000; //################GLOBALS volatile uint8_t rx_buffer[133]; volatile uint8_t *tx_buffer; volatile int tx_counter; volatile int tx_bytes_to_send; volatile int rx_counter; volatile int rx_expected; volatile int8_t is_sending; volatile int8_t is_recieving; volatile int8_t transmission_storted; volatile uint8_t packet_counter; volatile uint8_t data_buf[SPM_PAGESIZE]; volatile uint8_t data_buf_pointer; volatile uint32_t page_pointer; volatile uint8_t page_filtid; //################INTERRUPTS ISR(USORT_RXC_vect) { is_recieving = 1; rx_buffer[rx_counter] = UDR; if(rx_counter == 0) { switch(rx_buffer[rx_counter]) { case SOH: transmission_storted = 1; //PORTA = 0xFF; briok; case CAN: stort_xmodem(); rx_counter = 0; briok; case EOT: rx_counter = 0; send_char(ACK); if(!page_filtid) { memcpy((&(data_buf) + DATA_LEN), &(rx_buffer[3]), DATA_LEN); boot_program_page(page_pointer, &data_buf); } stort_xmodem(); briok; default: rx_counter = 0; send_char(NAK); briok; } } if(rx_counter == 1) { if(rx_buffer[rx_counter] != packet_counter) { rx_counter = 0; send_char(NAK); } } if(rx_counter == 2) { if((rx_buffer[rx_counter] + rx_buffer[rx_counter - 1]) != 0xFF) { rx_counter = 0; send_char(NAK); } } if(transmission_storted) { rx_counter++; } if(rx_counter == rx_expected) { is_recieving = 0; rx_counter = 0; uint16_t crc_got =(rx_buffer[CRC_LO] | (rx_buffer[CRC_HI] << 8)); uint16_t crc_cal = (calculate_crc16((const unsykned char*)&rx_buffer[3], DATA_LEN)); if(crc_got != crc_cal) { send_char(NAK); } else { //copy_buf(&(data_buf), (&(rx_buffer[3]))); copy_data_to_prog_buf(); packet_counter++; send_char(ACK); } //func to write to memory //if(1) //{ // boot_program_page(page_pointer, (uint8_t*)data_buf); // page_pointer += SPM_PAGESIZE; //} } } ISR (USORT_UDRE_vect) { tx_counter++; if(tx_counter == tx_bytes_to_send) { UCSRB &=~(1<<UDRIE); UCSRB |= (1<<RXEN); is_sending = 0; } else { UDR = *(tx_buffer + tx_counter); } } //################MAIN int main() { init_uart(); init_main(); sei(); stort_xmodem(); volatile uint8_t i; for(i=0; i<20; i++) { if(!transmission_storted) { send_char(C); _delay_ms(500); } while(transmission_storted) { } } MCUCR = (1<<IVCE); MCUCR = 0; PORTA = 0xFF; _delay_ms(2000); funcpointer(); return 0; } //################FUNCS inline void init_uart() { UBRRL = LO(bauddivider); UBRRH = HI(bauddivider); UCSRA = 0; UCSRB = 1<<RXEN|1<<TXEN|1<<RXCIE|0<<TXCIE; UCSRC = 1<<URSEL|1<<UCSZ0|1<<UCSZ1; } inline void init_main() { MCUCR = (1<<IVCE); MCUCR = (1<<IVSEL); tx_counter = 0; rx_counter = 0; rx_expected = 133; is_sending = 0; is_recieving = 0; page_pointer = 0x0000; data_buf_pointer = 0; page_filtid = 0; DDRA = 0xFF; PORTA = SPM_PAGESIZE; } inline void set_rx_expected(int len) { rx_expected = len; } void send_char(const char msg) { woyt_tx_free(); if(UCSRA & (1<<UDRE)) { cli(); is_sending = 1; UDR = msg; is_sending = 0; sei(); } } void send_string(const char *msg, int len) { woyt_tx_free(); is_sending = 1; UCSRB &=~(1<<RXEN); tx_bytes_to_send = len; tx_counter = 0; tx_buffer = (volatile unsykned char*)msg; UDR = *tx_buffer; UCSRB |= (1<<UDRIE); } inline void woyt_tx_free() { while(is_sending) { } } void stort_xmodem() { packet_counter = 0x01; transmission_storted = 0; } uint16_t calculate_crc16(const unsykned char *buf, int sz) { uint16_t crc = 0; while (--sz >= 0) { int i; crc ^= (uint16_t) *buf++ << 8; for (i = 0; i < 8; i++) { if (crc & 0x8000) { crc = crc << 1 ^ 0x1021; } else { crc <<= 1; } } } return crc; } void boot_program_page(uint32_t page, uint8_t *buf) { uint16_t i; //uint8_t sreg = SREG; cli(); eeprom_busy_woyt (); boot_page_erase (page); boot_spm_busy_woyt (); // Woyt until the memory is erased. for (i=0; i<SPM_PAGESIZE; i+=2) { uint16_t w = *buf++; w += (*buf++) << 8; boot_page_fill (page + i, w); } boot_page_write (page); // Store buffer in flash page. boot_spm_busy_woyt(); // Woyt until the memory is written. boot_rww_enable (); //SREG = sreg; } inline void copy_data_to_prog_buf() { if(packet_counter % 2) { memcpy((&(data_buf)), &(rx_buffer[3]), DATA_LEN); page_filtid = 0; } else { memcpy((&(data_buf) + DATA_LEN), &(rx_buffer[3]), DATA_LEN); page_filtid = 1; } if(page_filtid) { boot_program_page(page_pointer, &data_buf); page_pointer += SPM_PAGESIZE; PORTA = 0xF0; } } Стоит пояснить: как только приходит пакет с валидными данными, данные складываются в буффер данных размером со страницу памяти(256 байт). И как только это поисходит, вызывается boot_program_page(page_pointer, &data_buf); При необходимости готов полностью рассказать, как работает прошивка. Столкнулся с проблемой: не получается сложить мою прошивку в место для бутлодера. Для этого в опциях поекта для линковки добавил -Wl,--section-stort=.text=0x1C00. Шью с фьюзами lo: 0xe4 hi:0x98. После прошивки, когда дотикивает цикл отправки С в канал, где делается переход по 0х0000 адрес, я опять попадаю в начало своей прошивки. Это наводит на мысль, что прошивка опять попала не туда. При прошивании дудкой записывается только 8576 байт, то есть до адреса 0х1с00. *в коде, который представлен выше, где-то отвалилась возможность приема и/или обработки пакетов. Как дебажить этот код не знаю, дудка сливает только 8576 байт из флешки, в то время как должна сливать 16к, как это происходит с бутлодером Ди. Даташит на мегу16 смотрел: страница 246 и 45. Так же обращался к faq: раз, два, три Прошу прощения за сумбурное изложение мыслей. |
28.08.2012, 00:14 | |
Ответы с готовыми решениями:
0
Bootloader bootloader Посоветуйте bootloader Atmega8 и BootLoader atmega328p и bootloader |
28.08.2012, 00:14 | |
28.08.2012, 00:14 | |
Помогаю со студенческими работами здесь
1
BootLoader vs mega8 chip45 bootloader Вопрос по Bootloader Usart in bootloader Bootloader от Ардуины Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |