реклама на сайте
подробности

 
 
3 страниц V  < 1 2 3 >  
Reply to this topicStart new topic
> Bootloader для MSP430, как написать бутлоадер для МСП430
CAHTA_1939
сообщение Oct 29 2007, 20:36
Сообщение #16


Частый гость
**

Группа: Участник
Сообщений: 142
Регистрация: 11-08-07
Пользователь №: 29 713



я тут в msp430x1xx_user_guide прочитал что флеш память можно программировать если программа находится в ОЗУ...
а кук туда ее записать?
сорри если туплю... я в этом новичек и учусь...
Go to the top of the page
 
+Quote Post
rezident
сообщение Oct 29 2007, 20:53
Сообщение #17


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(CAHTA_1939 @ Oct 30 2007, 01:36) *
я тут в msp430x1xx_user_guide прочитал что флеш память можно программировать если программа находится в ОЗУ...

Совсем не обязательно. Программа программирования Flash может работать прямо из самой Flash. Только естественно, не из того же сектора, который в данный момент программируется. В MSP430 реализован автомат (контроллер Flash-памяти), который на время стирания/записи Flash сам тактирует ядро и подменяет текущую команду, выбираемую из Flash, командой "пустого" перехода - JMP PC.
Если вы читали User's Guide, то вопрос странный. Если не читали, то стоит почитать.
http://www.gaw.ru/html.cgi/txt/doc/micros/msp430/arh/5.htm
Цитата(CAHTA_1939 @ Oct 30 2007, 01:36) *
а кук туда ее записать?
сорри если туплю... я в этом новичек и учусь...

Дык банальным копированием smile.gif - скопировали код в ОЗУ и передали ему управление. Только этот кусок кода должен быть перемещаемым, т.е. работать с относительными локальными метками переходов. Ну и не быть слишком большим конечно же, помещаться в имеющийся на кристалле объем ОЗУ.
Go to the top of the page
 
+Quote Post
АДИКМ
сообщение Oct 30 2007, 13:13
Сообщение #18


Знающий
****

Группа: Свой
Сообщений: 630
Регистрация: 2-08-05
Пользователь №: 7 294



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


--------------------
летаю на пепелаце...
Go to the top of the page
 
+Quote Post
NoName
сообщение Nov 1 2007, 13:39
Сообщение #19


Участник
*

Группа: Участник
Сообщений: 36
Регистрация: 4-03-05
Из: Киев
Пользователь №: 3 078



Цитата(asket @ Oct 23 2007, 17:48) *
Это мне понятно, дело здесь в другом, допустим у нас несколько сегментов:

-Z(CODE)CODE=1100-1200
-Z(CODE)MYCODE=1200-1500

По умолчанию компилятор IAR помещает стандартные и служебные функции в сегмент CODE, то есть это означает, что если программист забыл указать сегмент, то компилятор автоматом поместит в сегмент --Z(CODE)CODE, то есть мне не хотелось сильно зависеть от данного сегмента, ибо большинство функции находятся в сегменте MYCODE, придется тогда над каждой функцией писать #pragma location="MYCODE". В старой версии IAR мне понравилось тем, что распределение по сегментам определяется один раз, достаточно наверху с помошью прагмы указать сегмент и тогда все функции данного модуля окажутся в этом сегменте, а новой версии этого почему-то не нашел, приходится объявлять сегмент каждой функции, что не есть хорошо..


для Си
void func_name ( void ) @ "MYCODE"
{
_NOP();
}

недочитал %), ответ не по вопросу ...

Сообщение отредактировал NoName - Nov 1 2007, 14:12
Go to the top of the page
 
+Quote Post
KARLSON
сообщение Oct 5 2011, 07:31
Сообщение #20


Знающий
****

Группа: Свой
Сообщений: 604
Регистрация: 5-05-06
Из: Нижегородская обл.
Пользователь №: 16 819



Здравствуйте. Собрался писать загрузчик. Т.к. в MSP430F2410 выводы своего загрузчика находятся на P1.1 и P2.2, которые заняты.
Почитав форум узнал:
- что лучше делать 2 проекта (один загрузчик, другой рабочий проект), получается 2 hex файла? Первый – загрузчик - прошивается через JTAG? А после, через интерфейс загрузчика?
- что-то делается с таблицами векторов. Так называемый remapping. Но так и не понял как это делается. Смею предположить, что переписывается всего лишь xcl файл.
С программированием флеш памяти (INFO) знаком.
Написал функцию прошивальщика с общением по UART.(Прикрепил) Правда ещё не проверял в действии.
Вопросы: с чего продолжить? Как оформить таблицу векторов? Как оформить функцию прошивальщик.

Прикрепленные файлы
Прикрепленный файл  Program_FLASH.rar ( 1.3 килобайт ) Кол-во скачиваний: 51
 


--------------------
Кризис - это не отсутствие денег, а отсутствие идей! Учитесь и никаких кризисов не будет.
Go to the top of the page
 
+Quote Post
rezident
сообщение Oct 5 2011, 17:26
Сообщение #21


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(KARLSON @ Oct 5 2011, 12:31) *
- что лучше делать 2 проекта (один загрузчик, другой рабочий проект), получается 2 hex файла?
Да.
Цитата(KARLSON @ Oct 5 2011, 12:31) *
Первый – загрузчик - прошивается через JTAG? А после, через интерфейс загрузчика?
Не обязательно. Можно обе прошивки hex-файла объединить. Ведь пересекаться по расположению в памяти они не должны.
Цитата(KARLSON @ Oct 5 2011, 12:31) *
- что-то делается с таблицами векторов. Так называемый remapping. Но так и не понял как это делается. Смею предположить, что переписывается всего лишь xcl файл.
Не совсем так. В xcl-файле проекта пользовательского исходника нужно объявить сегмент, который компилятор не должен использовать для размещения кода. В исходнике же бутлоадера - наоборот, компилятор должен использовать только этот выделенный сегмент. На месте векторов прерываний должны быть адреса переходов. А сами обработчики прерываний располагаются где-то в другом месте (в неперезаписываемом сегменте Flash или в ОЗУ). Хотя по-моему в бутлоадере использовать прерывания это моветон, да и незачем, если только у вас нет жесткого требования обновления firmware прямо во время работы программы без прерывания ее функционирования. Хотя в этом случае образец новой firmware предварительно еще где-то сохранить нужно, проверив его на валидность. Работать в бутлоадере с UART можно и без прерываний, по опросу флагов готовности.
Go to the top of the page
 
+Quote Post
KARLSON
сообщение Oct 10 2011, 05:20
Сообщение #22


Знающий
****

Группа: Свой
Сообщений: 604
Регистрация: 5-05-06
Из: Нижегородская обл.
Пользователь №: 16 819



При двух проектах, ведь будет две функции main();
А при включении контроллера запускаться должна рабочая программа? И по команде по UART вызываться функция бутлоадера, вернее переход на адрес во флешь?


--------------------
Кризис - это не отсутствие денег, а отсутствие идей! Учитесь и никаких кризисов не будет.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Oct 10 2011, 06:57
Сообщение #23


Гуру
******

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



QUOTE (KARLSON @ Oct 10 2011, 08:20) *
А при включении контроллера запускаться должна рабочая программа?
А если ее нет или она записалась не до конца?
Как раз наоборот - при включении питания запускается загрузчик, проверяет целостность рабочей программы, и если она признана живой - запускает ее. Если нет - ожидает поступления по UART (или другому интерфейсу перепрошивки) команды перепрошивки.

QUOTE (KARLSON @ Oct 10 2011, 08:20) *
И по команде по UART вызываться функция бутлоадера, вернее переход на адрес во флешь?
Это да. Если приложение запущено, то оно запускает загрузчик по команде. Но не переходом на его main(), а переходом на начало его стартап-кода, который штатно подготовит ОЗУ для запуска main() загрузчика.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
KARLSON
сообщение Oct 10 2011, 11:34
Сообщение #24


Знающий
****

Группа: Свой
Сообщений: 604
Регистрация: 5-05-06
Из: Нижегородская обл.
Пользователь №: 16 819



И так. Создаю пример.
Вопрос: правильно ли прописаны xcl файлы?
Как вызвать в загрузчике приложение и наоборот))

Msp430F2410 описание памяти:
// Interrupt vectors: 32
// Peripheral units: 0-01FF
// Information memory (FLASH): 1000-10FF
// Read/write memory (RAM): 1100-20FF
// Read-only memory (FLASH): 2100-FFFF

Bootloader
Код
#include <io430.h>
#include "Titl.h"
#include "function.cpp"
#include "UART0.cpp"

void main( void )
{
  WDTCTL = WDTPW + WDTHOLD;
  Init_DCO_16MHz();
  Init_USCI_A0();
  Init_FLASH();
  P3OUT = 0;
  P3DIR = BIT3;
  if (Check_Flash())
  {// проверка прошла удачно
    // переход в приложение
    
  }
  else
  {// неудачная проверка
    // ждём команду по UART перепрошивки
      _EINT();
      while(1)
      {
        for(unsigned int i=0; i<65000; i++);
        for(unsigned int i=0; i<65000; i++);
        P3OUT ^= BIT3;
      }
  }
}


xcl файл Bootloader
Код
// -------------------------------------
// Code
//
-Z(CODE)CSTART,ISR_CODE,CODE_ID=EC00-FFBF
-P(CODE)CODE=EC00-FFBF

// -------------------------------------
// Interrupt vectors
//
-Z(CODE)INTVEC=FFC0-FFFF
-Z(CODE)RESET=FFFE-FFFF


Приложение
Код
#include <io430.h>
#include "Titl.h"
#include "function.cpp"
#include "UART0.cpp"

void main( void )
{
  WDTCTL = WDTPW + WDTHOLD;
  Init_DCO_16MHz();
  Init_USCI_A0();
  
  P3OUT = 0;
  P3DIR = BIT3;
  _EINT();
  while(1)
  {// приложение
        for(unsigned int i=0; i<65000; i++);
        for(unsigned int i=0; i<65000; i++);
        P3OUT ^= BIT3;
  }
}

#pragma vector = USCIAB0RX_VECTOR
__interrupt void USCIA0_RX(void)
{//1
  if(UCA0STAT&UCADDR)  
  {//2
  Clovo_Data_RX0=0;
  //---------------------------------------------------
    switch(UCA0RXBUF)
        {
        case    0:    // команда для прошивке
                                              // переход на прошивку
                UCA0CTL1 &=~ UCDORM;    //Переключиться на прием неадресных символов            
                                              break;
                            default:        break;
        }
  }//2
}// 1

xcl файл Приложения
Код
// -------------------------------------
// Code
//

-Z(CODE)CSTART,ISR_CODE,CODE_ID=2200-EBFF
-P(CODE)CODE=2200-EBFF

// -------------------------------------
// Interrupt vectors
//

-Z(CODE)INTVEC=21C0-21FF
-Z(CODE)RESET=21FE-21FF





--------------------
Кризис - это не отсутствие денег, а отсутствие идей! Учитесь и никаких кризисов не будет.
Go to the top of the page
 
+Quote Post
rezident
сообщение Oct 10 2011, 19:44
Сообщение #25


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(KARLSON @ Oct 10 2011, 16:34) *
И так. Создаю пример.
Bootloader на плюсах? wacko.gif Весьма оригинально!
Цитата(KARLSON @ Oct 10 2011, 16:34) *
Вопрос: правильно ли прописаны xcl файлы?
Как вызвать в загрузчике приложение и наоборот))
main для приложения должена компилироваться как функция по заранее определенному адресу. Тогда не составляет сложности вызвать эту функцию по указателю. О том, как разместить функцию по определенному адресу, написано в разделах Placing code and data и Pragma directives документа EW430_CompilerReference.pdf. Обязательно следует учитывать, что еще до вызова функции main в скомпилированной программе сначала выполняется установка/инициализация указателя стека, затем вызывается функция low_level_init, а потом выполняется функция очистки и начальной инициализации глобальных и статических переменных (?cstart_init_zero). Так что если вы будете вызывать пользовательскую программу по адресу main, то вышеописанные функции вам придется реализовывать "вручную". Ну либо ищите как можно узнать или зарезервировать адрес метки __program_start (?cstart_begin в случае С), которая располагается по адресу перехода от вектора прерывания RESET и с которой начинается выполнение программы. Обычно эта метка совпадает с началом сегмента CODE.
Все это справедливо лишь для "чистого" Си. C++ для программирования MSP430 я ни разу не использовал.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Oct 11 2011, 06:12
Сообщение #26


Гуру
******

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



QUOTE (rezident @ Oct 10 2011, 22:44) *
Bootloader на плюсах? wacko.gif Весьма оригинально!
Ой, да бросьте. Гораздо удобнее чем на обычных Сях. Накладных расходов нет, если пользоваться головой.
QUOTE (rezident @ Oct 10 2011, 22:44) *
main для приложения должена компилироваться как функция по заранее определенному адресу. Тогда не составляет сложности вызвать эту функцию по указателю.
Зачем? Достаточно перейти по тому адресу, который находится в векторе Reset приложения. И все необходимые действия (cstartup) будут выполнены, и адрес этого вектора известен.

KARLSON: Включать .cpp в другие файлы - путь в корне неправильный. Вам необходимо почитать про заголовочные (header) файлы и раздельную компиляцию.

CODE
-Z(CODE)INTVEC=FFC0-FFFF
-Z(CODE)RESET=FFFE-FFFF
Бить область векторов на две (выделать вектор сброса в отдельную область) не обязательно. Мне кажется вторая строка лишняя - вектор сброса компилятор тоже кладет в INTVEC. Во втором файле то же самое. Но идею вы ухватили верно. И подумайте, как быть с прерываниями - у приложения будут свои обработчики и их надо вызывать, а "настоящие" вектора находятся в области загрузчика. Я на GCC делал так:
CODE
__attribute__ ((section(".app_vectors"))) struct
{
    flash_t::address_t App_image_size;
    void *Vectors[INT_VECTORS_COUNT - 1];
    void (*ResetVector)();
} Application;

#define TRAMP(name, vector)                                         \
extern "C" __attribute__((__naked__)) void Tramp_##name()           \
{                                                                   \
    asm volatile("BR    %0\n\t" ::"m"(InterruptVectors[vector]));   \
}


TRAMP(DAC12,                0);
TRAMP(DMA,                  1);
TRAMP(USCIAB1TX_VECTOR,     2);
TRAMP(USCIAB1RX_VECTOR,     3);
.....
typedef void (*vector_t)();

__attribute__ ((section(".vectors"))) extern vector_t const  VectorTable[INT_VECTORS_COUNT] =
{
    Tramp_DAC12,
    Tramp_DMA,
    Tramp_USCIAB1TX_VECTOR,
    Tramp_USCIAB1RX_VECTOR,
Вы можете сделать что-то подобное в отдельном асм-файле.
Если загрузчику тоже нужны обработчики прерываний, то надо копировать вектора нужной части программы в ОЗУ и адрес для этого перехода брать из ОЗУ:
CODE
    if (!crc)                               // Application Section crc ok
    {
        DRIVER(MANUAL_BOOT, OUTPUT);        // set MANUAL_PROG as output
        uint_fast8_t i = INT_VECTORS_COUNT - 1; // do not copy reset vector
        while(i--)
        {
            InterruptVectors[i] = Application.Vectors[i];
        }
        Application.ResetVector();
    }


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


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
rezident
сообщение Oct 11 2011, 15:08
Сообщение #27


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(Сергей Борщ @ Oct 11 2011, 11:12) *
Зачем? Достаточно перейти по тому адресу, который находится в векторе Reset приложения. И все необходимые действия (cstartup) будут выполнены, и адрес этого вектора известен.
В векторе сброса располагается адрес старта бутлоадера, а не пользовательского приложения. Или я что-то не понимаю? laughing.gif
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Oct 11 2011, 17:32
Сообщение #28


Гуру
******

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



QUOTE (rezident @ Oct 11 2011, 18:08) *
В векторе сброса располагается адрес старта бутлоадера, а не пользовательского приложения. Или я что-то не понимаю? laughing.gif
В векторе Reset приложения. Приложение ведь имеет свой полный комплект векторов, в том числе и вектор Reset c адресом перехода как раз в нужную точку старта.
У меня так laughing.gif


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
rezident
сообщение Oct 11 2011, 17:59
Сообщение #29


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(Сергей Борщ @ Oct 11 2011, 22:32) *
В векторе Reset приложения. Приложение ведь имеет свой полный комплект векторов, в том числе и вектор Reset c адресом перехода как раз в нужную точку старта.
Дык ведь тогда вектора RESET бутлоадера и приложения будут наложены друг на друга.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Oct 11 2011, 22:32
Сообщение #30


Гуру
******

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



QUOTE (rezident @ Oct 11 2011, 20:59) *
Дык ведь тогда вектора RESET бутлоадера и приложения будут наложены друг на друга.
Ну почему же? Посмотрите сообщение №24 - две программы, две таблицы векторов по разным адресам.
А... кажется понял. У нас несколько разная трактовка понятия "вектор". Я под вектором подразумеваю содержимое, т.е. сам адрес "куда переходить", а не саму ячейку, т.е. "адрес, из которого процессор берет адрес перехода". Поэтому и таблица "моих" векторов у приложения может быть своя, совершенно независимая. Да, адреса из таблицы приложения берутся не аппаратно, а посредством функций-помошников ("трамплинов"), указатели на которые сидят на "железных", "ваших" wink.gif векторах. Во всяком случае такой подход позволяет ценой одного дополнительного косвенного перехода и двух байт ОЗУ на каждый вектор иметь совершенно независимые обработчики у приложения и загрузчика. Причем в целях экономии ОЗУ таким образом можно охватить не всю таблицу, а лишь физически реализованные в процессоре прерывания.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post

3 страниц V  < 1 2 3 >
Reply to this topicStart new topic
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 27th July 2025 - 22:38
Рейтинг@Mail.ru


Страница сгенерированна за 0.01559 секунд с 7
ELECTRONIX ©2004-2016