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

я тут в msp430x1xx_user_guide прочитал что флеш память можно программировать если программа находится в ОЗУ...

а кук туда ее записать?

сорри если туплю... я в этом новичек и учусь...

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


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

я тут в 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

а кук туда ее записать?

сорри если туплю... я в этом новичек и учусь...

Дык банальным копированием :) - скопировали код в ОЗУ и передали ему управление. Только этот кусок кода должен быть перемещаемым, т.е. работать с относительными локальными метками переходов. Ну и не быть слишком большим конечно же, помещаться в имеющийся на кристалле объем ОЗУ.

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


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

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

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

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


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

Это мне понятно, дело здесь в другом, допустим у нас несколько сегментов:

 

-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

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


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

Здравствуйте. Собрался писать загрузчик. Т.к. в MSP430F2410 выводы своего загрузчика находятся на P1.1 и P2.2, которые заняты.

Почитав форум узнал:

- что лучше делать 2 проекта (один загрузчик, другой рабочий проект), получается 2 hex файла? Первый – загрузчик - прошивается через JTAG? А после, через интерфейс загрузчика?

- что-то делается с таблицами векторов. Так называемый remapping. Но так и не понял как это делается. Смею предположить, что переписывается всего лишь xcl файл.

С программированием флеш памяти (INFO) знаком.

Написал функцию прошивальщика с общением по UART.(Прикрепил) Правда ещё не проверял в действии.

Вопросы: с чего продолжить? Как оформить таблицу векторов? Как оформить функцию прошивальщик.

Program_FLASH.rar

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


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

- что лучше делать 2 проекта (один загрузчик, другой рабочий проект), получается 2 hex файла?
Да.

Первый – загрузчик - прошивается через JTAG? А после, через интерфейс загрузчика?
Не обязательно. Можно обе прошивки hex-файла объединить. Ведь пересекаться по расположению в памяти они не должны.

- что-то делается с таблицами векторов. Так называемый remapping. Но так и не понял как это делается. Смею предположить, что переписывается всего лишь xcl файл.
Не совсем так. В xcl-файле проекта пользовательского исходника нужно объявить сегмент, который компилятор не должен использовать для размещения кода. В исходнике же бутлоадера - наоборот, компилятор должен использовать только этот выделенный сегмент. На месте векторов прерываний должны быть адреса переходов. А сами обработчики прерываний располагаются где-то в другом месте (в неперезаписываемом сегменте Flash или в ОЗУ). Хотя по-моему в бутлоадере использовать прерывания это моветон, да и незачем, если только у вас нет жесткого требования обновления firmware прямо во время работы программы без прерывания ее функционирования. Хотя в этом случае образец новой firmware предварительно еще где-то сохранить нужно, проверив его на валидность. Работать в бутлоадере с UART можно и без прерываний, по опросу флагов готовности.

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


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

При двух проектах, ведь будет две функции main();

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

 

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


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

А при включении контроллера запускаться должна рабочая программа?
А если ее нет или она записалась не до конца?

Как раз наоборот - при включении питания запускается загрузчик, проверяет целостность рабочей программы, и если она признана живой - запускает ее. Если нет - ожидает поступления по UART (или другому интерфейсу перепрошивки) команды перепрошивки.

 

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

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


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

И так. Создаю пример.

Вопрос: правильно ли прописаны 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

 

 

 

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


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

И так. Создаю пример.
Bootloader на плюсах? :wacko: Весьма оригинально!

Вопрос: правильно ли прописаны 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 я ни разу не использовал.

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


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

Bootloader на плюсах? :wacko: Весьма оригинально!
Ой, да бросьте. Гораздо удобнее чем на обычных Сях. Накладных расходов нет, если пользоваться головой.

main для приложения должена компилироваться как функция по заранее определенному адресу. Тогда не составляет сложности вызвать эту функцию по указателю.
Зачем? Достаточно перейти по тому адресу, который находится в векторе Reset приложения. И все необходимые действия (cstartup) будут выполнены, и адрес этого вектора известен.

 

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

 

-Z(CODE)INTVEC=FFC0-FFFF 
-Z(CODE)RESET=FFFE-FFFF

Бить область векторов на две (выделать вектор сброса в отдельную область) не обязательно. Мне кажется вторая строка лишняя - вектор сброса компилятор тоже кладет в INTVEC. Во втором файле то же самое. Но идею вы ухватили верно. И подумайте, как быть с прерываниями - у приложения будут свои обработчики и их надо вызывать, а "настоящие" вектора находятся в области загрузчика. Я на GCC делал так:

__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,

Вы можете сделать что-то подобное в отдельном асм-файле.

Если загрузчику тоже нужны обработчики прерываний, то надо копировать вектора нужной части программы в ОЗУ и адрес для этого перехода брать из ОЗУ:

    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();
    }

 

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

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


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

Зачем? Достаточно перейти по тому адресу, который находится в векторе Reset приложения. И все необходимые действия (cstartup) будут выполнены, и адрес этого вектора известен.
В векторе сброса располагается адрес старта бутлоадера, а не пользовательского приложения. Или я что-то не понимаю? :laughing:

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


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

В векторе сброса располагается адрес старта бутлоадера, а не пользовательского приложения. Или я что-то не понимаю? :laughing:
В векторе Reset приложения. Приложение ведь имеет свой полный комплект векторов, в том числе и вектор Reset c адресом перехода как раз в нужную точку старта.

У меня так :laughing:

 

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


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

В векторе Reset приложения. Приложение ведь имеет свой полный комплект векторов, в том числе и вектор Reset c адресом перехода как раз в нужную точку старта.
Дык ведь тогда вектора RESET бутлоадера и приложения будут наложены друг на друга.

 

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


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

Дык ведь тогда вектора RESET бутлоадера и приложения будут наложены друг на друга.
Ну почему же? Посмотрите сообщение №24 - две программы, две таблицы векторов по разным адресам.

А... кажется понял. У нас несколько разная трактовка понятия "вектор". Я под вектором подразумеваю содержимое, т.е. сам адрес "куда переходить", а не саму ячейку, т.е. "адрес, из которого процессор берет адрес перехода". Поэтому и таблица "моих" векторов у приложения может быть своя, совершенно независимая. Да, адреса из таблицы приложения берутся не аппаратно, а посредством функций-помошников ("трамплинов"), указатели на которые сидят на "железных", "ваших" ;) векторах. Во всяком случае такой подход позволяет ценой одного дополнительного косвенного перехода и двух байт ОЗУ на каждый вектор иметь совершенно независимые обработчики у приложения и загрузчика. Причем в целях экономии ОЗУ таким образом можно охватить не всю таблицу, а лишь физически реализованные в процессоре прерывания.

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


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

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

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

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

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

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

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

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

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

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