|
|
  |
STM32 Bootloader |
|
|
|
Apr 28 2016, 06:03
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Я написал отдельную программу - бутлоадер. Чтоб разместить ее во флеш нужно изменить стартап файл и линкер файл. и тут у меня трудности. может кто нибудь рассказать как это делать? под бутлоадер я хочу отвести первые две страницы. линкер и стартап в принципе изменять не надо. насчет главной программы. в линкере заменил Код MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 64K } На Код MEMORY { FLASH (rx) : ORIGIN = 0x08001000, LENGTH = 1024K RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 64K } и в system_stm32f30x.c заменил Код #define VECT_TAB_OFFSET 0x0 На Код #define VECT_TAB_OFFSET 0x1000 а что еще надо поменять?
|
|
|
|
|
Apr 28 2016, 06:17
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
QUOTE (Jenya7 @ Apr 28 2016, 09:03)  CODE FLASH (rx) : ORIGIN = 0x08001000, LENGTH = 1024K Вы уехали за границу доступной памяти. Осетра-то урежте  , в смысле LENGTH укоротите на размер загрузчика. И в загрузчике аналогично, чтобы получить ошибку если он вдруг налезет на приложение. QUOTE (Jenya7 @ Apr 28 2016, 09:03)  а что еще надо поменять? Зависит от того, что и как вы наворотили в загрузчике. У меня линкер сразу после векторов добавляет размер прошивки в словах (чтобы загрузчик знал, до куда считать CRC), а также резервируется место под CRC.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Apr 28 2016, 06:42
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Цитата(Сергей Борщ @ Apr 28 2016, 12:17)  Вы уехали за границу доступной памяти. Осетра-то урежте  , в смысле LENGTH укоротите на размер загрузчика. И в загрузчике аналогично, чтобы получить ошибку если он вдруг налезет на приложение. Зависит от того, что и как вы наворотили в загрузчике. У меня линкер сразу после векторов добавляет размер прошивки в словах (чтобы загрузчик знал, до куда считать CRC), а также резервируется место под CRC. спасибо. укоротил. вроде бежит главная программа но как то странно. запускаю через дебагер – пишет no source file named main.c. и через 30 секунд - это у меня таймаут в бутлоудере - бежит главная программа. добавил в Startup Script Код # Reconfigure vector table offset register to match the application location set *0xe000ed08 = 0x1000
# Get the application stack pointer (First entry in the application vector table) set $sp = *(unsigned int*)0x1000
# Get the application entry point (Second entry in the application vector table) set $pc = *(unsigned int*)0x1004 ничего не изменилось. кстати а как линкер знает размер прошивки? Вы его изменяете после каждой копиляции? вроде решил проблему. вот полный код скрипта. Код # Set flash parallelism mode to 32, 16, or 8 bit when using STM32 F2/F4 microcontrollers # Uncomment next line, 2=32 bit, 1=16 bit and 0=8 bit parallelism mode #monitor flash set_parallelism_mode 2
# Set character encoding set host-charset CP1252 set target-charset CP1252
# Reset to known state monitor reset
# Load the program executable load
# Reconfigure vector table offset register to match the application location set *0xe000ed08 = 0x1000
# Get the application stack pointer (First entry in the application vector table) set $sp = *(unsigned int*)0x1000
# Get the application entry point (Second entry in the application vector table) set $pc = *(unsigned int*)0x1004
# Reset the chip to get to a known state. Remove "monitor reset" command # if the code is not located at default address and does not run by reset. #monitor reset
# Enable Debug connection in low power modes (DBGMCU->CR) set *0xE0042004 = (*0xE0042004) | 0x7
# Set a breakpoint at main(). tbreak main
# Run to the breakpoint. continue
Сообщение отредактировал Jenya7 - Apr 28 2016, 08:11
|
|
|
|
|
Apr 28 2016, 10:50
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
QUOTE (Jenya7 @ Apr 28 2016, 09:42)  кстати а как линкер знает размер прошивки? Он же сам ее собрал, кто же лучше него может знать? CODE .text : { _image_start = .; KEEP(*(.isr_vector))
LONG((_image_end - _image_start) / 4); /* application size, in 4-byte words */ ............. /* после всех text, romem и data: */ .text.crc : { . = . + 4; /* reserve space for CRC */ _image_end = .; } > TEXT
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Apr 28 2016, 15:50
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Цитата(Сергей Борщ @ Apr 28 2016, 15:50)  Он же сам ее собрал, кто же лучше него может знать? Код .text : { _image_start = .; KEEP(*(.isr_vector))
LONG((_image_end - _image_start) / 4); /* application size, in 4-byte words */ ............. /* после всех text, romem и data: */ .text.crc : { . = . + 4; /* reserve space for CRC */ _image_end = .; } > TEXT А у меня в линкере этого нет LONG((_image_end - _image_start) / 4); Вы сами добавили?
|
|
|
|
|
Apr 28 2016, 17:30
|
Частый гость
 
Группа: Участник
Сообщений: 132
Регистрация: 6-02-16
Из: г. Баку
Пользователь №: 90 364

|
Цитата(Jenya7 @ Apr 28 2016, 19:50)  А у меня в линкере этого нет LONG((_image_end - _image_start) / 4); Вы сами добавили? Пример просто он привел. С новой директивой линкера. Интересной. А Вы под Ac6 проект используете? Или под gcc.
|
|
|
|
|
Apr 29 2016, 09:42
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Цитата(AleksBak @ Apr 28 2016, 23:30)  Пример просто он привел. С новой директивой линкера. Интересной. А Вы под Ac6 проект используете? Или под gcc. У меня Atollic TrueStudio. там GCC. Цитата(Сергей Борщ @ Apr 28 2016, 23:51)  У вас там и резервирования места под CRC нет. Да, сам добавил. Скрипт линкера - не какая-нибудь священная корова, а такая же часть проекта, как и все остальные файлы исходников. а как вы тогда определяете _image_end и _image_start? я не понимаю кто придумал такой ужасный смнтаксис в линкере. похоже на шпионскую шифровку. есть столько красивых скриптовых языков.
|
|
|
|
|
Apr 29 2016, 10:04
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
QUOTE (Jenya7 @ Apr 29 2016, 12:42)  а как вы тогда определяете _image_end и _image_start? Там все показано: CODE _image_start = .; ..... _image_end = .; Документацию на линкер пересказывать не буду, извините. "Чтение информации из интернета вслух - 100 евро в час". QUOTE (Jenya7 @ Apr 29 2016, 12:42)  я не понимаю кто придумал такой ужасный смнтаксис в линкере. похоже на шпионскую шифровку. есть столько красивых скриптовых языков. "Жалуйтесь в лигу сексуальных реформ"  или напишите свой линкер с красивым скриптовым языком.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Apr 29 2016, 10:33
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Цитата(Сергей Борщ @ Apr 29 2016, 15:04)  Там все показано: Код _image_start = .; ..... _image_end = .; Документацию на линкер пересказывать не буду, извините. "Чтение информации из интернета вслух - 100 евро в час". "Жалуйтесь в лигу сексуальных реформ"  или напишите свой линкер с красивым скриптовым языком. спасибо. почитал по ссылке. довольно доходчивое объяснение.
|
|
|
|
|
May 2 2016, 07:15
|
Частый гость
 
Группа: Участник
Сообщений: 132
Регистрация: 6-02-16
Из: г. Баку
Пользователь №: 90 364

|
Цитата(Jenya7 @ May 2 2016, 10:48)  еще такой вопрос хотел задать. мне надо принять по CAN прошивку и положить во флеш. может есть пример как это делается? разбить hex файл на строки и посылать построчно? а как по CAN принимать? насколько я понимаю приемный FIFO содержит 8 байт. прошивать по 8 байт или накапливать пакет,скажем размером в страницу и затем прошивать? А зачем hex файл посылать? Он же текстовый. Сразу в бинарном виде же лучше - тем более тут CAN. И контрольную сумму не забыть потом. У Вас по CAN какой-то хост имеется что ли?
|
|
|
|
|
May 2 2016, 08:08
|
Профессионал
    
Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075

|
Цитата(AleksBak @ May 2 2016, 13:15)  А зачем hex файл посылать? Он же текстовый. Сразу в бинарном виде же лучше - тем более тут CAN. И контрольную сумму не забыть потом. У Вас по CAN какой-то хост имеется что ли? нет. обычный CAN. принимаю данные по прерыванию. Код void USB_LP_CAN1_RX0_IRQHandler(void) { if((CAN1->RF0R & CAN_RF0R_FMP0)!=0) /* check if a message is filtered and received by FIFO 0 */ { CAN_ReceiveData = CAN1->sFIFOMailBox[0].RDLR; /* read data */ CAN_CmdType = CAN1->sFIFOMailBox[0].RDHR; CAN_Identifier = CAN1->sFIFOMailBox[0].RIR; CAN1->RF0R |= CAN_RF0R_RFOM0; /* release FIFO */ data_ready = 1; } else { //error_flag |= CAN_ERR; CAN1->TSR |= CAN_TSR_ABRQ0; CAN1->IER &= ~CAN_IER_ERRIE; } } непонятно как организовать протокол приема бин файла. сам бут выглядит пока так Код int boot_main(void) {
__disable_irq();
GPIO_Config(); CAN_Config(); Start_TIM2();
__enable_irq();
//load parameters from flash memcpy(&flashParams, (uint32_t*)FLASH_PAGE127, sizeof(flashParams)); // notify other party that we are alive CAN_Send(UNIT_ID , READY, 0); /* Infinite loop */ while (1) { //get data from CAN if (data_ready) { data_ready = 0; WriteAppToFlash(); }
//timeout to exit to main application if (sec_count > TIMEOUT) { sec_count = 0; if (flashParams.state == LAST_BOOT_OK) { JumpToApp(); } else //try to program flash from the buffer { } }
} } WriteAppToFlash() в сыром виде выглядит так Код void WriteAppToFlash(void) { /* Porgram APP to FLASH -------------------------------------------------------------*/
// Unlock the Flash FLASH_Unlock();
/* Clear All pending flags */ FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPERR | FLASH_FLAG_BSY);
uint32_t done = 0; uint32_t page; uint32_t page_addr; uint32_t page_addr_end;
/* Erase the FLASH pages */ for(page = 0; page < 20; page++) //main program takes 20 pages { page_addr = (page * FLASH_PAGE_SIZE) + APPLICATION_ADDRESS; FLASHStatus = FLASH_ErasePage(page_addr); if (FLASHStatus != FLASH_COMPLETE) break; }
/* Program Flash */ page = 0; while (page < 20 || !done) { Address = (page * FLASH_PAGE_SIZE) + APPLICATION_ADDRESS; page_addr_end = Address + FLASH_PAGE_SIZE; while((Address < page_addr_end)) { // Get packet from CAN //?????????
//Program packet to flash FLASHStatus = FLASH_ProgramWord(Address, Data); Address = Address + 4; addr_data = addr_data +4; if (FLASHStatus != FLASH_COMPLETE) { //done = 1; break; } } page++; }
FLASH_Lock();
/* Jump to User define Application Address */ JumpToApp(); }
Сообщение отредактировал Jenya7 - May 2 2016, 07:24
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|