Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: IAR + SAM7S
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
KAlex
Есть проект, в котором надо динамически выделять под массив данных область в памяти. Желательно как можно большего размера.
Как на стадии компиляции узнать размер свободной SRAM?
Возможно ли определить это в уже работающей программе?
zltigo
Цитата(KAlex @ Nov 12 2007, 14:07) *
Возможно ли определить это в уже работающей программе?

А в чем проблемы - начальный адрес Вашего массива Вам известен. Размер RAM у контроллера тоже.
Вычесть из второго первое smile.gif.
KAlex
Цитата(zltigo @ Nov 12 2007, 15:22) *
А в чем проблемы - начальный адрес Вашего массива Вам известен.

Неизвестен, в этом то и вопрос.
zltigo
Цитата(KAlex @ Nov 12 2007, 14:33) *
Неизвестен, в этом то и вопрос.

Ерунду какую-то сказали sad.gif если есть обьект, то естественно во время исполнения у него есть адрес.
Для Вашего случая заводите сегмент (можете в нем и какой-нибудь минимальный массивчик завести), линкуете его в конец. Адрес сегмента (или массива известен) размер RAM тоже. Все.
KAlex
Цитата(zltigo @ Nov 12 2007, 16:18) *
Для Вашего случая заводите сегмент (можете в нем и какой-нибудь минимальный массивчик завести), линкуете его в конец.

А как сказать IAR-у, что этот массив надо линковать последним. Я с этим ни разу не сталкивался.
zltigo
Цитата(KAlex @ Nov 12 2007, 15:27) *
А как сказать IAR-у, что этот массив надо линковать последним.

Явно указав его имя в списке для линкера последним. Конкретика зависит от версии IAR - у 4.x и 5.x линкеры разные.
Если 4.x то например в XCL файле добавляем:
Код
-D_HEAP_RTOS_SIZE=1000  // 4Kb - Dummy minimal space for My Memory Manager
-Z(DATA)HEAP_RTOS+_HEAP_RTOS_SIZE=RAMSTART-RAMEND     // For My memory manager

Ну а дальше:
Код
extern ulong RAMEND;
extern ulong RAMSTART;
#pragma segment="HEAP_RTOS"

    printf( "\tRAM use:%lu Heap:%8X Size:%lu\r",
                                 (ulong)(__segment_begin( "HEAP_RTOS" ))-(ulong)&RAMSTART,
                                 __segment_begin( "HEAP_RTOS" ),
                                (ulong)&RAMEND - (ulong)(__segment_begin( "HEAP_RTOS" )) + 1 );
KAlex
Спасибо. То что надо.
Kitsok
zltigo

А вот немного не в тему.

Есть девайс на SAM7, общающийся через USB с хостом, и хочется сделать через тот-же интерфейс сделать обновление прошивки.

Приложение работает под FreeRTOS.
Так вот идея такая:
Получаем по USB команду на апгрейд прошивки, получаем собственно прошивку, запрещаем наглухо прерывания, копируем прошивку в heap, в heap-же копируем функцию записи во флеш, делаем необходимые проверки и передаем управление на эту функцию.

Криво или можно так сделать?
Сергей Борщ
Цитата(Kitsok @ Nov 18 2007, 10:16) *
копируем прошивку в heap, в heap-же копируем функцию записи во флеш, делаем необходимые проверки и передаем управление на эту функцию.
И незадолго до конца работы этой функции пропадает питание. Устройство можно возвращать изготовителю. Было несколько обсуждений на эту тему. Вкратце - загрузчик должен находиться в том же сегменте, что и вектора и получать управление при включении питания. А дальше решать - передавать управление основной программе или делать апгрейд.
Kitsok
Цитата(Сергей Борщ @ Nov 18 2007, 15:34) *
И незадолго до конца работы этой функции пропадает питание. Устройство можно возвращать изготовителю. Было несколько обсуждений на эту тему. Вкратце - загрузчик должен находиться в том же сегменте, что и вектора и получать управление при включении питания. А дальше решать - передавать управление основной программе или делать апгрейд.


Спасибо за ссылку, почитаю.

С опасением полностью согласен.
Причина, по которой я не горю желанием писать полноценный бутлоадер (для поиска: загрузчик, bootloader, бутлодырь wink.gif) - необходимо реализовать весь стек USB - других интерфейсов у устройства попросту нет...
Сергей Борщ
Цитата(Kitsok @ Nov 18 2007, 21:32) *
необходимо реализовать весь стек USB - других интерфейсов у устройства попросту нет...
А ОЗУ внешнее? Внутреннего-то не хватит, чтобы всю прошивку в heap поместить. Для прошивки достаточно держать в ОЗУ функцию из нескольких команд
Код
__ramfunc __arm void FlashCommand_RAM(uint32_t command)
{
    AT91C_BASE_MC->MC_FCR = command;
    while(!(AT91C_BASE_MC->MC_FSR & AT91C_MC_FRDY));
}
Возможно имеет смысл ее держать в ОЗУ постоянно. Все остальное может жить в защищенном от стирания секторе флеш. Может имеет смысл при приеме прошивки складывать ее в свободную область флеш, а загрузчик будет копировать из этой области в рабочие адреса? Тогда сбои питания не страшны - одна из копий прошивки всегда будет целой, а сам копировщик вообще нестираемым.
Kitsok
Цитата(Сергей Борщ @ Nov 19 2007, 16:13) *
А ОЗУ внешнее? Внутреннего-то не хватит, чтобы всю прошивку в heap поместить. Для прошивки достаточно держать в ОЗУ функцию из нескольких команд
Код
__ramfunc __arm void FlashCommand_RAM(uint32_t command)
{
    AT91C_BASE_MC->MC_FCR = command;
    while(!(AT91C_BASE_MC->MC_FSR & AT91C_MC_FRDY));
}
Возможно имеет смысл ее держать в ОЗУ постоянно. Все остальное может жить в защищенном от стирания секторе флеш. Может имеет смысл при приеме прошивки складывать ее в свободную область флеш, а загрузчик будет копировать из этой области в рабочие адреса? Тогда сбои питания не страшны - одна из копий прошивки всегда будет целой, а сам копировщик вообще нестираемым.


ОЗУ встроенное, SAM7S256, но прошивка ограничивается размером в 16 кб, больше мне и не надо.

Рассматриваю возможность дописывания аппликухи и организации dual firmware.

А вот глупый вопрос - можно ли работая из флеша писать другие сектора этого флеша, или обязательно копировать себя в RAM и запускаться оттуда?

Потому как если можно, то изменения будут касаться исключительно проверки версии и CRC с дальнейшей передачей управления.

Хотя криво это все, по-хорошему, надо бутлоадер писать а-ля SAM-BA и не выпендриваться.
Сергей Борщ
Цитата(Kitsok @ Nov 20 2007, 12:52) *
А вот глупый вопрос - можно ли работая из флеша писать другие сектора этого флеша, или обязательно копировать себя в RAM и запускаться оттуда?
Все, кроме приведенной мной выше функции может работать из флеша. На время выполнения этой функции флеш блокируется (поэтому либо запрещайте прерывания, либо переносите обработчики и вектора в ОЗУ).
Цитата(Kitsok @ Nov 20 2007, 12:52) *
Хотя криво это все, по-хорошему, надо бутлоадер писать а-ля SAM-BA и не выпендриваться.
Тем более что в USB есть (специальный класс?) возможность загрузки firmware. У атмела в апликухах кажется что-то было. Может и не так страшно?
Kitsok
Цитата(Сергей Борщ @ Nov 20 2007, 15:30) *
Тем более что в USB есть (специальный класс?) возможность загрузки firmware. У атмела в апликухах кажется что-то было. Может и не так страшно?


Да в общем-то, наверное я склонюсь к этому варианту wink.gif
_dem
имхо, имелось в виду немного не то :

Так как флеш пишется постранично, и у флеш контроллера есть внутренний буфер на одну страницу, то на время подготовки этой страницы (записи значений в буфер) можно работать из флеша

а вот во время выполнения команды записи (предложенная Сергеем функция) все должно быть остановлено и сама функция должна работать из RAM

Учитывая небольшой размер вашей прошивки, я бы вообще порекомендовал вам после запуска копировать прошивку в RAM и делать REMAP - и работайте с флешем когда и как вам хочется. Естественно, прошивка должна быть слинкована с правильными адресами (работа из RAM). А копирование можно сделать в cstartup на ассемблере.
Kitsok
Цитата(_dem @ Nov 21 2007, 00:21) *
Учитывая небольшой размер вашей прошивки, я бы вообще порекомендовал вам после запуска копировать прошивку в RAM и делать REMAP - и работайте с флешем когда и как вам хочется. Естественно, прошивка должна быть слинкована с правильными адресами (работа из RAM). А копирование можно сделать в cstartup на ассемблере.


Про флеш понятно. Про ремап - нет, буду по второму кругу доку читать, но пока не понятно.
В частности:
Ресетится контроллер, передается управление по адресу 0x0, который мемори контроллером транслируется в 0x00100000 (флеш).
Выполняется там что-то, копируется что-то из флеша в страницу памяти по адресу 0x00200000(РАМ). Потом мы ставим бит remap, следующая инструкция откуда возьмется - из RAM или из FLASH?

Еще одна непонятка - как нужно настроить компилятор, куда что линковать?
Получается что для бутлоадера нужно прописывать файл линкеру, что мы "живем" по адресам 0x00100000? Тогда после ресета pc=0, первая инструкция - переход по реальному адресу. Ну а приложение нужно размещать по адресу 0x00, и в бутлоадере делать копирование флеша в память, ремап и передачу управления на 0x00. Правильно?
Сергей Борщ
Цитата(Kitsok @ Nov 21 2007, 14:22) *
Ресетится контроллер, передается управление по адресу 0x0, который мемори контроллером транслируется в 0x00100000 (флеш).
Выполняется там что-то, копируется что-то из флеша в страницу памяти по адресу 0x00200000(РАМ). Потом мы ставим бит remap, следующая инструкция откуда возьмется - из RAM или из FLASH?
Давайте представим это так: есть три области - с нуля, с 0x00100000 (флеш), и с 0x00200000(ОЗУ). Если РС указывает на вторую область, программа исполняется из флеш. Если на третью - из ОЗУ. Если на первую - то зависит от ремапа. Т.е. в первой области мы имеем "зеркало" второй или третьей. Поэтому в момент ремапа программа должна исполняться из второй или третьей (она может вообще всегда исполняться из второй или третьей, а в нулевую попадать только по исключениям, чтобы считать вектор). Это в SAM7. В LPC несколько иначе - там "отражается" только область 0x40 байт на вектора. Поэтому ответ такой - из следующего адреса. А что окажется по этому адресу - зависит от адреса (если вторая область - флеш, если третья - ОЗУ) и ремапа(если первая)
Цитата(Kitsok @ Nov 21 2007, 14:22) *
Еще одна непонятка - как нужно настроить компилятор, куда что линковать? Получается что для бутлоадера нужно прописывать файл линкеру, что мы "живем" по адресам 0x00100000? Тогда после ресета pc=0, первая инструкция - переход по реальному адресу. Ну а приложение нужно размещать по адресу 0x00, и в бутлоадере делать копирование флеша в память, ремап и передачу управления на 0x00. Правильно?
Почти. У меня так: загрузчик живет по адресам 0x00100000 - 0x00100FFF (нулевой сектор флеш), файл SAM7_boot.xcl. Приложение живет вслед за загрузчиком, начиная с 0x00101000 (первый сектор флеш и далее), файл SAM7S64_boot_app.xcl. При включении питания или сбросе флеш отражена на нулевые адреса, на месте векторов оказываются вектора загрузчика, из вектора ресета считывается переход на загрузчик в адреса 0x00100000 - 0x00100FFF. Загрузчик получает управление. Если надо передать управление приложению, то загрузчик берет вектора приложения из адресов 0x00101000-0x0010103F, копирует их в озу по адресам 0x00200000-0x0020003F (эта область зарезервирована и в загрузчике и в приложении, чтобы там не оказались какие-либо данные). Загрузчик (работая в адресах 0x00100000 - 0x00100FFF) запрещает прерывания и делает ремап. При этом ОЗУ отражается на нулевые адреса и в области векторов оказываются скопированные в 0x00200000-0x0020003F вектора приложения. Загрузчик передает управление на нулевой адрес, т.е. на вектор ресет приложения. Из вектора считывается команда перехода на cstartup приложения, в адреса 0x00101040....
Kitsok
Цитата(Сергей Борщ @ Nov 21 2007, 17:20) *
У меня так: загрузчик живет по адресам 0x00100000 - 0x00100FFF (нулевой сектор флеш), файл SAM7_boot.xcl. Приложение живет вслед за загрузчиком, начиная с 0x00101000 (первый сектор флеш и далее), файл SAM7S64_boot_app.xcl. При включении питания или сбросе флеш отражена на нулевые адреса, на месте векторов оказываются вектора загрузчика, из вектора ресета считывается переход на загрузчик в адреса 0x00100000 - 0x00100FFF. Загрузчик получает управление. Если надо передать управление приложению, то загрузчик берет вектора приложения из адресов 0x00101000-0x0010103F, копирует их в озу по адресам 0x00200000-0x0020003F (эта область зарезервирована и в загрузчике и в приложении, чтобы там не оказались какие-либо данные). Загрузчик (работая в адресах 0x00100000 - 0x00100FFF) запрещает прерывания и делает ремап. При этом ОЗУ отражается на нулевые адреса и в области векторов оказываются скопированные в 0x00200000-0x0020003F вектора приложения. Загрузчик передает управление на нулевой адрес, т.е. на вектор ресет приложения. Из вектора считывается команда перехода на cstartup приложения, в адреса 0x00101040....


Ну, собственно, именно такой механизм я и имел в виду. Разница лишь в том, что я зачем-то (может, для скорости? wink.gif) предложил копировать все приложение из флеша в память, а потом - remap.
Важно то, что после ресета у нас pc=0, а следующая инструкция уже выполняется из диапазона 0x00100000-... Или, другими словами, таблица векторов (которую мы копируем) "живет" всегда по адресам из 0x000000-0x000003F, а переводит всегда на реальные адреса во флеше. Ну или в RAM, если копировать приложение.

Спасибо большое всем!
Похоже, до меня доперло wink.gif
Kitsok
Цитата(Kitsok @ Nov 21 2007, 17:43) *
Похоже, до меня доперло wink.gif

... не до конца.

Приложение у нас живет начиная с адреса 0x00101000-..., соответственно вектора его лежат в 0x00101000-0x00100103F, а дальше - само приложение, вплоть до 0x0010FFFF

После ремапа эти адреса будут отражены на 0x00001000-0x0000FFFF.
В загрузчике мы скопировали 0x00101000-0x0010103F в 0x00100000-0x0010003F, и, если в xlc так и указано, у нас все пучком.

Но после ремапа остается дыра 0x00000040-0x00000FFF?

Вариант - собирать приложение по адресам 0x00000000, бутлоадером копировать приложение в RAM целиком и делать ремап. Но криво опять...

Что-то я не догоняю?
Сергей Борщ
Цитата(Kitsok @ Nov 22 2007, 00:55) *
... не до конца.

Приложение у нас живет начиная с адреса 0x00101000-..., соответственно вектора его лежат в 0x00101000-0x00100103F, а дальше - само приложение, вплоть до 0x0010FFFF

После ремапа эти адреса будут отражены на 0x00001000-0x0000FFFF.
Нет. Перед ремапом в нулевые адреса отражена область 0x00100000... т.е. на месте векторов (0x00000000-0x0000003F) отражены вектора загрузчика (0x00100000-0x0010003F), дальше отражен загрузчик и приложение (но это не принципиально). После ремапа на нулевые адреса отражается область 0x00200000..., т.е. RAM, а туда перед ремапом загрузчик копирует вектора приложения. Загрузчик и приложение остаются на своем месте по адресам во флеш.
Kitsok
Цитата(Сергей Борщ @ Nov 22 2007, 14:35) *
Нет. Перед ремапом в нулевые адреса отражена область 0x00100000... т.е. на месте векторов (0x00000000-0x0000003F) отражены вектора загрузчика (0x00100000-0x0010003F), дальше отражен загрузчик и приложение (но это не принципиально). После ремапа на нулевые адреса отражается область 0x00200000..., т.е. RAM, а туда перед ремапом загрузчик копирует вектора приложения. Загрузчик и приложение остаются на своем месте по адресам во флеш.


Это понятно. Но дыра-то во флеше все-равно останется. Стоп. А в этой дыре не загрузчик ли? wink.gif wink.gif wink.gif Надо больше спать...
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.