Миландр

Ключевым подразделением нашей компании является Центр Проектирования интегральных микросхем
Текущее время: 2018-май-26 09:18

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 12 ] 
Автор Сообщение
 Заголовок сообщения: Сделать "бутлоудер"
СообщениеДобавлено: 2016-апр-18 17:59 
Не в сети

Зарегистрирован: 2016-янв-29 17:53
Сообщения: 54
Надо принять прошивку через CAN, записать во флеш и запустить прошивку которую приняли. Как сделать?
Моя программа примерно выглядит так:
Открыть Программа
Код:
#define USE_MDR1986VE9x
#define USE_JTAG_A
#include "MDR32F9Qx_config.h"           // Keil::Device:Startup_MDR1986BE9x
#include "MDR32Fx.h"                    // Device header
#include "MDR32F9Qx_can.h"              // Keil::Drivers:CAN
#include "MDR32F9Qx_eeprom.h"           // Keil::Drivers:EEMPROM
#include "MDR32F9Qx_rst_clk.h"          // Keil::Drivers:RST_CLK
#include "MDR32F9Qx_port.h"             // Keil::Drivers:PORT
#define USE_MDR1986VE9x
#define USE_JTAG_A
////// Рабочая программа для записи во флеш

#define RX_BUF 0
#define TX_BUF 1
#define ADDRESS_APPS      (uint32_t) 0x8001000

__RAMFUNC void jumpToApplication(void){      // прыгает на программу)))
   typedef  void (*pFunction)(void);
   pFunction Jump_To_Application;
   uint32_t JumpAddress;

   if( (*(__IO uint32_t*)ADDRESS_APPS) != 0xffffffff){
//      deInitPeriph();
      SCB->VTOR = (uint32_t)(ADDRESS_APPS);
      JumpAddress = *(__IO uint32_t*) (ADDRESS_APPS+4);   
      Jump_To_Application = (pFunction) (JumpAddress); 
      __set_MSP(*(__IO uint32_t*) ADDRESS_APPS);           
      Jump_To_Application();                           
   }
}
__RAMFUNC void EEPROM_Reload()      // прошивка через CAN1   // my
{
   uint32_t i;      // для считывание флеш памяти!
   
   CAN_RxMsgTypeDef RxMsg;
   uint16_t RxMsgID;
   uint32_t AdressSdvig = 0;   //костыль! должно быть 0
      // for tests******
   CAN_TxMsgTypeDef TxMsg;
   TxMsg.IDE     = CAN_ID_STD;
   TxMsg.DLC     = 8;
   TxMsg.PRIOR_0 = DISABLE;

   //   EEPROM_EraseAllPages(EEPROM_All_Banks_Select);

   
   while(1)
   {
      if((CAN_GetStatus(MDR_CAN1) & CAN_STATUS_RX_READY) == 1)
      {
         CAN_GetRawReceivedData(MDR_CAN1, RX_BUF, &RxMsg);
         CAN_ITClearRxTxPendingBit(MDR_CAN1, RX_BUF, CAN_STATUS_RX_READY);
         RxMsgID =  CAN_EXTID_TO_STDID(RxMsg.Rx_Header.ID);      // получение ID

         if(RxMsgID == 2)      // получение BIN-file
         {
            EEPROM_ProgramWord((ADDRESS_APPS+4*AdressSdvig),EEPROM_All_Banks_Select,RxMsg.Data[1]);
            AdressSdvig++;
            EEPROM_ProgramWord((ADDRESS_APPS+4*AdressSdvig),EEPROM_All_Banks_Select,RxMsg.Data[0]);
            AdressSdvig++;
         }
         if(RxMsgID == 3)      // конец передачи
         {            
            jumpToApplication();
         }
         TxMsg.Data[0] = RxMsg.Data[0];
         TxMsg.Data[1] = RxMsg.Data[1];
         CAN_Transmit(MDR_CAN1, TX_BUF, &TxMsg);
      }
   }
}

void AllConfig(void);
/*
ID map
01 - начать передавать BIN-file
02 - передача BIN-file
03 - конец передачи
*/
int main(void)
{
   //   // for tests******
   CAN_TxMsgTypeDef TxMsg;
   TxMsg.IDE     = CAN_ID_STD;
   TxMsg.DLC     = 8;
   TxMsg.PRIOR_0 = DISABLE;
   
   CAN_RxMsgTypeDef RxMsg;
   volatile uint16_t RxMsgID;
   AllConfig();
   while(1)
   {
      if((CAN_GetStatus(MDR_CAN1) & CAN_STATUS_RX_READY) == 1)
      {
         CAN_GetRawReceivedData(MDR_CAN1, RX_BUF, &RxMsg);
         CAN_ITClearRxTxPendingBit(MDR_CAN1, RX_BUF, CAN_STATUS_RX_READY);
         RxMsgID =  CAN_EXTID_TO_STDID(RxMsg.Rx_Header.ID);      // получение ID
         TxMsg.Data[0] = RxMsg.Data[0];
         TxMsg.Data[1] = RxMsg.Data[1];
         CAN_Transmit(MDR_CAN1, TX_BUF, &TxMsg);
         if(RxMsgID == 1)
         {
            EEPROM_Reload();   // получение новой прошивки!
         }
      }
   }
}
void AllConfig()      // все настройки
{
   // настройки HSE & ConfigClock
   RST_CLK_DeInit();
   RST_CLK_HSEconfig(RST_CLK_HSE_ON);
   while (RST_CLK_HSEstatus() != SUCCESS);
   RST_CLK_CPU_PLLconfig(RST_CLK_CPU_PLLsrcHSEdiv1,RST_CLK_CPU_PLLmul1);//CPU_C1_SEL[1:0] and PLL multiplication factor
   RST_CLK_CPU_PLLcmd(DISABLE);
   RST_CLK_CPUclkPrescaler(RST_CLK_CPUclkDIV1);         //CPU_C3_SEL[3:0]
   RST_CLK_CPU_PLLuse(DISABLE);                                 //CPU_C2_SEL[1:0]??
   RST_CLK_CPUclkSelection(RST_CLK_CPUclkCPU_C3);      //Final MUX for CLK
   
   // Clock
   RST_CLK_PCLKcmd(RST_CLK_PCLK_RST_CLK, ENABLE);   // RST_CLK
   RST_CLK_PCLKcmd(RST_CLK_PCLK_CAN1, ENABLE);         // CAN1
   RST_CLK_PCLKcmd(RST_CLK_PCLK_PORTA, ENABLE);      // PORTA
   RST_CLK_PCLKcmd(RST_CLK_PCLK_EEPROM, ENABLE);      // EEPROM
   
   // PORTA pin6, pin7
   PORT_InitTypeDef PORT_InitStructure;
   PORT_StructInit(&PORT_InitStructure);
   PORT_Init(MDR_PORTA, &PORT_InitStructure);
   PORT_InitStructure.PORT_OE      = PORT_OE_IN;
   PORT_InitStructure.PORT_FUNC   =   PORT_FUNC_ALTER;
   PORT_InitStructure.PORT_MODE   =   PORT_MODE_DIGITAL;
   PORT_InitStructure.PORT_SPEED   =   PORT_SPEED_MAXFAST;
   PORT_InitStructure.PORT_Pin      = (PORT_Pin_6 | PORT_Pin_7);
   PORT_Init(MDR_PORTA, &PORT_InitStructure);
   
   // CAN1
   CAN_InitTypeDef  sCAN;
   CAN_BRGInit(MDR_CAN1,CAN_HCLKdiv1);
   CAN_DeInit(MDR_CAN1);
   CAN_StructInit (&sCAN);
  sCAN.CAN_ROP  = DISABLE;
  sCAN.CAN_SAP  = DISABLE;
  sCAN.CAN_STM  = DISABLE;
  sCAN.CAN_ROM  = DISABLE;
  sCAN.CAN_PSEG = CAN_PSEG_Mul_2TQ;
  sCAN.CAN_SEG1 = CAN_SEG1_Mul_4TQ;
  sCAN.CAN_SEG2 = CAN_SEG2_Mul_4TQ;
  sCAN.CAN_SJW  = CAN_SJW_Mul_4TQ;
  sCAN.CAN_SB   = CAN_SB_3_SAMPLE;
  sCAN.CAN_BRP  = 31;
  CAN_Init (MDR_CAN1,&sCAN);
  CAN_Cmd(MDR_CAN1, ENABLE);
   /* Disable all CAN1 interrupt */
   CAN_ITConfig( MDR_CAN1, CAN_IT_GLBINTEN | CAN_IT_RXINTEN | CAN_IT_TXINTEN |
                CAN_IT_ERRINTEN | CAN_IT_ERROVERINTEN, DISABLE);
  /* Enable CAN1 interrupt from receive buffer */
  CAN_RxITConfig( MDR_CAN1 ,(1<<RX_BUF), ENABLE);
  /* Enable CAN1 interrupt from transmit buffer */
  CAN_TxITConfig( MDR_CAN1 ,(1<<TX_BUF), ENABLE);
  /* receive buffer enable */
  CAN_Receive(MDR_CAN1, RX_BUF, DISABLE);
}
Закрыть


Библиотеки EEPROM и CAN поставил записываться в IRAM1. Прошивка корректно отправляется, запись во флеш тоже происходит корректно. А вот ф-ция jumpToApplication() не работает.
Кто может помочь? В чем может быть проблема?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Сделать "бутлоудер"
СообщениеДобавлено: 2016-апр-18 22:40 
Не в сети
Аватара пользователя

Зарегистрирован: 2011-авг-21 18:55
Сообщения: 249
Переход на загрузчик я делаю так - первый спойлер viewtopic.php?p=13345#p13345
Кстати, не забыли прошивку разметить с адреса 0x8001000, а то, может там 0x8000000.

_________________
Hack the Planet!


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Сделать "бутлоудер"
СообщениеДобавлено: 2017-фев-27 11:51 
Не в сети

Зарегистрирован: 2012-апр-12 18:33
Сообщения: 14
Добрый день! Вопрос такой, как передать управление из загрузчика основной программе, которая лежит по адресу 0x08001000. При использовании ассемблерной инструкции BX микроконтроллер уходит в прерывание HardFault. Кусок кода, который дан выше в ссылке, не рабочий. Так как переходит там вообще не по адресу, а значению, которое лежит по нужному адресу. Помогите пожалуйста, вот сам код:
void main()
{
SCB->VTOR = Address_main_prog; //0x08001000

__DSB();
#pragma asm
LDR R0, = Address_main_prog
BX R0
#pragma endasm
}

P.S. Среда CodeMaster от Phyton.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Сделать "бутлоудер"
СообщениеДобавлено: 2017-фев-27 13:45 
Не в сети

Зарегистрирован: 2010-авг-30 19:12
Сообщения: 389
читайте внимательно описание ядра.Первые два адреса прошивки содержат значение для инициализации стека и адрес первой инструкции для исполнения.
Поэтому выход из загрузчика сделан
Цитата:
там вообще не по адресу, а значению, которое лежит по нужному адресу.

а
Цитата:
При использовании ассемблерной инструкции BX микроконтроллер уходит в прерывание HardFault
потому, что не может найти инструкции для исполнения.

_________________
О сколько нам открытий чудных
Готовит просвященья дух,
И опыт - сын ошибок трудных ... (Пушкин)

Пергаменты не утоляют жажду ("Фауст",Гете)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Сделать "бутлоудер"
СообщениеДобавлено: 2017-фев-28 08:01 
Не в сети

Зарегистрирован: 2012-апр-12 18:33
Сообщения: 14
Проверяла все с переходом программы на саму себя и не правильно задавала адрес, поэтому пример и не работал, теперь все понятно, спасибо.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Сделать "бутлоудер"
СообщениеДобавлено: 2018-янв-09 13:47 
Не в сети

Зарегистрирован: 2012-июл-24 19:43
Сообщения: 79
Добрый день!
Тоже озадачился созданием вторичного загрузчика. Увидел в теме кусок кода от R Max - вставил его в свою программу. Пока что во Flash из программы не пишу, а только делаю переход. Конкретно записал сперва в микроконтроллер программу загрузчика, а потом без стирания предыдущих записей (отметил в опциях программирования "Do not erase") - программу мигания светодиодом.
По идее предполагал, что программа загрузчика отсчитает таймаут и передаст управление программе мигания светодиодом. Впринципе, после таймаута светодиод замигал, но при этом в терминал повалил мусор. Убираю переход по адресу из программы загрузчика - мусора после окончания отсчета нет. Записываю программу мигания светодиодом только одну - тоже мусора нет, а вместе есть..
Решил, может быть загрузчик занимает на флеши больший объем - поставил адрес перехода 0x08010000 - не помогло.
Попробовал вынести функцию перехода на исполняемую программу в отдельный файл и поставил исполнение из ОЗУ - все равно мусор. Что может быть за бяка.
Настройки проекта загрузчика
Изображение
Настройки проекта мигания светодиодом
Изображение
Проекты заготовки загрузчика и мигания светодиодом прилагаю
Loader.rar - проект заготовки загрузчика
LED_BL.rar - тестовая программа с которой проверялось
Заранее спасибо за помощь


Вложения:
LED_BL.rar [152.65 КБ]
Скачиваний: 46
Loader.rar [313.22 КБ]
Скачиваний: 46
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Сделать "бутлоудер"
СообщениеДобавлено: 2018-янв-09 16:38 
Не в сети

Зарегистрирован: 2017-апр-26 14:51
Сообщения: 105
Откуда: ПКК "Миландр"
На первый взгляд:

Цитата:
В терминал повалил мусор
- это какой терминал имеется ввиду?

Если Uart1 то,
После SCB->VTOR = MainVectorTableAddr, используемый в Loader Uart по идее должен был отрубиться при отработке SystemInit в новом Reset_Handler. Обработчик UART1_IRQHandler в светодиодах тоже стал по умолчанию из startup_MDR32F9x.s.

_________________
Отдел технической поддержки support@milandr.ru


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Сделать "бутлоудер"
СообщениеДобавлено: 2018-янв-09 17:35 
Не в сети

Зарегистрирован: 2012-июл-24 19:43
Сообщения: 79
Добрый вечер!
Прошу прощения, не уточнил - для вывода сообщений использую терминал, подключенный к UART2.
Пока не было перехода, выводилась надпись о том, что далее будет загружаться программа.
После того, как ввел переход, надпись не выводится (потом вообще закомментировал :-)), а начинает сыпаться мусор.
По-идее, думал тоже, что UART отрубится.. или перед переходом его надо отключить в программе?
Поставил вместо мигания светодиодом программу, которая шлет "Hello world" в тот же UART - все равно отправляется мусор.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Сделать "бутлоудер"
СообщениеДобавлено: 2018-янв-09 19:32 
Не в сети
Аватара пользователя

Зарегистрирован: 2011-авг-21 18:55
Сообщения: 249
Vasiliy писал(а):
На первый взгляд:

Цитата:
В терминал повалил мусор
- это какой терминал имеется ввиду?

Если Uart1 то,
После SCB->VTOR = MainVectorTableAddr, используемый в Loader Uart по идее должен был отрубиться при отработке SystemInit в новом Reset_Handler. Обработчик UART1_IRQHandler в светодиодах тоже стал по умолчанию из startup_MDR32F9x.s.


+1
Я использую свой Startup.s, в котором удалена функция SystemInit (кстати в Startup.s для 1986ВЕ1Т сделано также самими vendor-ами), чтобы обойтись без повторной настройки PLL и уже запущенной периферии:
; Reset handler
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT __main
LDR R0, =__main
BX R0
ENDP
А SystemInit, который отработает в Startup.s в основной программе по идее обнулит настройки UART_CLK и порта D

_________________
Hack the Planet!


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Сделать "бутлоудер"
СообщениеДобавлено: 2018-янв-09 20:00 
Не в сети

Зарегистрирован: 2012-июл-24 19:43
Сообщения: 79
2 R Max, огромное спасибо - мусор на терминале исчез после того, как закомментировал SystemInit. С остальным, думаю, завтра разбираться буду


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Сделать "бутлоудер"
СообщениеДобавлено: 2018-янв-18 08:38 
Не в сети

Зарегистрирован: 2012-июл-24 19:43
Сообщения: 79
Добавил в проект загрузчика функции записи и стирания флеши, но залитая через X-modem прошивка не хочет запускаться.
Функции работы с флеш-памятью сделал по образу и подобию функций из проекта DFU-загрузчика R Max. Единственное, что выделил отдельный таймер на формирование задержек.
Для загрузки использую BIN-файл, сгенерированный командой
Код:
SET PATH=C:\Keil\ARM\BIN40\
fromelf.exe ".\LED.axf" --bin --output ".\LED.bin"

Код вызова функций записи во флеш:
Код:
temp=(frame[t]<<24) | (frame[t+1]<<16) | (frame[t+2]<<8) | (frame[t+3]);
irqs=NVIC->ISER[0];
NVIC->ICER[0]=0xFFFFFFFF;
EEPROM_ErasePage((MainVectorTableAddr+addr_shift), 0);
EEPROM_Write((MainVectorTableAddr+addr_shift), temp, 0);
NVIC->ISER[0]=irqs;
t=t+4;
addr_shift=addr_shift+0x10;

менял строчку формирования temp на
Код:
temp=(frame[t+3]<<24) | (frame[t+2]<<16) | (frame[t+2]<<8) | (frame[t]);

результат такой же
В свойствах файла с функциями работы с флеш (flash.c) отмечено, чтоб запускался из оперативной памяти. Я так понимаю, что для заголовочного файла это не нужно.
Проект и BIN-файл во вложении
Loader2.rar - проект загрузчика
LED.rar - BIN файл загружаемой программы


Вложения:
LED.rar [810 байт]
Скачиваний: 42
Loader2.rar [458.81 КБ]
Скачиваний: 38
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Сделать "бутлоудер"
СообщениеДобавлено: 2018-янв-24 13:25 
Не в сети

Зарегистрирован: 2012-июл-24 19:43
Сообщения: 79
Вроде бы более-менее довел до кондиции проект.
Оказалось, что программа не стирала память - задержку поставил 40 мкс вместо 40 мс ну и небольшие доделки связанные с тем, что стирается страница, а записывается за один раз только 32-разрядное слово и т.д.
В общем, выкладываю проект на всеобщее обозрение - вдруг кому пригодится. Программа "кушает" BIN-файлы, загружаемые по протоколу X-modem. Терминал подключается к UART2 (RS232 платы LDM-Helper c 1986ВЕ92)Записываемая программа должна занимать адресное пространство во флеши начиная с 0x08001000.
HEX-файлы, выдаваемые Keil конвертировал в BIN утилитой, приложенной к сообщению. Также прикладываю и сам проект загрузчика.


Вложения:
hex2bin.rar [21.95 КБ]
Скачиваний: 45
Loader2.rar [474.69 КБ]
Скачиваний: 46
Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 12 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 4


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
cron
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB