Перейти к содержанию
    

STM32 Bootloader

Я написал отдельную программу - бутлоадер. Чтоб разместить ее во флеш нужно изменить стартап файл и линкер файл. и тут у меня трудности. может кто нибудь рассказать как это делать?

под бутлоадер я хочу отвести первые две страницы. линкер и стартап в принципе изменять не надо.

насчет главной программы. в линкере заменил

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

а что еще надо поменять?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

  FLASH (rx)      : ORIGIN = 0x08001000, LENGTH = 1024K

Вы уехали за границу доступной памяти. Осетра-то урежте ;) , в смысле LENGTH укоротите на размер загрузчика. И в загрузчике аналогично, чтобы получить ошибку если он вдруг налезет на приложение.

а что еще надо поменять?
Зависит от того, что и как вы наворотили в загрузчике. У меня линкер сразу после векторов добавляет размер прошивки в словах (чтобы загрузчик знал, до куда считать CRC), а также резервируется место под CRC.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вы уехали за границу доступной памяти. Осетра-то урежте ;) , в смысле 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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

кстати а как линкер знает размер прошивки?
Он же сам ее собрал, кто же лучше него может знать?

    .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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Он же сам ее собрал, кто же лучше него может знать?

    .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); Вы сами добавили?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А у меня в линкере этого нет LONG((_image_end - _image_start) / 4); Вы сами добавили?

Пример просто он привел. С новой директивой линкера. Интересной. А Вы под Ac6 проект используете? Или под gcc.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А у меня в линкере этого нет LONG((_image_end - _image_start) / 4); Вы сами добавили?
У вас там и резервирования места под CRC нет. Да, сам добавил. Скрипт линкера - не какая-нибудь священная корова, а такая же часть проекта, как и все остальные файлы исходников.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Пример просто он привел. С новой директивой линкера. Интересной. А Вы под Ac6 проект используете? Или под gcc.

У меня Atollic TrueStudio. там GCC.

 

У вас там и резервирования места под CRC нет. Да, сам добавил. Скрипт линкера - не какая-нибудь священная корова, а такая же часть проекта, как и все остальные файлы исходников.

а как вы тогда определяете _image_end и _image_start? я не понимаю кто придумал такой ужасный смнтаксис в линкере. похоже на шпионскую шифровку. есть столько красивых скриптовых языков.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

а как вы тогда определяете _image_end и _image_start?
Там все показано:

     _image_start = .;
.....
     _image_end = .;

Документацию на линкер пересказывать не буду, извините. "Чтение информации из интернета вслух - 100 евро в час".

 

я не понимаю кто придумал такой ужасный смнтаксис в линкере. похоже на шпионскую шифровку. есть столько красивых скриптовых языков.
"Жалуйтесь в лигу сексуальных реформ" ;) или напишите свой линкер с красивым скриптовым языком.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Там все показано:

     _image_start = .;
.....
     _image_end = .;

Документацию на линкер пересказывать не буду, извините. "Чтение информации из интернета вслух - 100 евро в час".

 

"Жалуйтесь в лигу сексуальных реформ" ;) или напишите свой линкер с красивым скриптовым языком.

спасибо. почитал по ссылке. довольно доходчивое объяснение.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

еще такой вопрос хотел задать.

мне надо принять по CAN прошивку и положить во флеш. может есть пример как это делается?

разбить hex файл на строки и посылать построчно? а как по CAN принимать? насколько я понимаю приемный FIFO содержит 8 байт. прошивать по 8 байт или накапливать пакет,скажем размером в страницу и затем прошивать?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

еще такой вопрос хотел задать.

мне надо принять по CAN прошивку и положить во флеш. может есть пример как это делается?

разбить hex файл на строки и посылать построчно? а как по CAN принимать? насколько я понимаю приемный FIFO содержит 8 байт. прошивать по 8 байт или накапливать пакет,скажем размером в страницу и затем прошивать?

А зачем hex файл посылать? Он же текстовый. Сразу в бинарном виде же лучше - тем более тут CAN. И контрольную сумму не забыть потом. У Вас по CAN какой-то хост имеется что ли?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А зачем 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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...