STM32 и Дзен. Компиляция и запуск отдельных программ.

По просьбам трудящихся решил поделиться своими наработками.



Возможно, не все, описанное тут, будет правильным решением. Некоторые вещи я делал либо исходя из своих поверхностных представлений о том, как это должно работать, либо вообще по интуиции.
Если в комментариях кто-то отпишется, укажет на ошибки и посоветует более правильное решение — буду очень благодарен.
Может кого-то эта тема заинтересует, и совместными усилиями можно будет что-нибудь эдакое выдать, чтобы потом все желающие могли использовать.

Суть в следующем.
Имеется плата, на которой стоит микроконтроллер STM32 и, например, SD-карточка. Идеальный вариант, если есть SRAM, подключенный по FSMC, но не обязательно. Внутренней памяти, на первое время, хватит.

Что нужно: компилить в Keil (или, возможно, другой среде) программу, заливать ее на SD-карточку и запускать на контроллере.

Как будем запускать?
Сразу на ум приходят два очевидных варианта:
1) Если программа небольшая, в несколько килобайт — заливаем ее в RAM и оттуда запускаем.
2) Если программа побольше — предварительно ее переписываем во внутренний флеш и запускаем из него.

Ну а если программа занимает больше, чем свободно во внутреннем флеше, единственный выход — внешний RAM по FSMC.

В этой статье остановлюсь на первом варианте.

Этап первый. SD и FAT.


Подробно описывать не буду. На эту тему много всего написано как в инете, так и в этом сообществе.
SD-карточку можно подключить по SPI, можно по SDIO (если контроллер F103). И то и то есть в примерах стандартной периферийной библиотеки от ST.
Файловую систему легко поднять с помощью библиотеки FatFs. О ней, вроде, тоже были статьи.
И вообще, можно и без файловой системы обойтись, главное, чтобы можно было откуда-нибудь считать предварительно откомпиленную программу.

Этап второй. Подготовка проекта с программой.



В моем контроллере 64кб оперативы. Считаю, что «32 килобайта хватит каждому»: грузить будем по адресу 0x20008000 — половина RAM.
Нужно скомпилить проект так, чтобы все адреса были расчитаны исходя из этого адреса.



Обязательно делаем .hex — файл. Из него потом сделаем бинарник, который зальем на SD-карточку.



Также советую включить C Compiler Listing, чтобы можно было проконтролировать как код уложится.



Ставим галочку One ELF Section per Function, в дефайны добавляем тип контроллера:



Ну и напоследок, указываем базовый адрес и точку входа во вкладке Linker.



Ну и пишем код, наподобие этого:

#include "stm32f10x.h"
uint32_t _main(int argc, char *argv[], uint32_t core_addr)
{
    // что-нибудь тут делаем
    return 123;
}


Компилим, получаем .hex-файл.

Открываем .txt и .hex, смотрим чтобы _main обязательно был вначале:

                  _main PROC
;;;10     
;;;11     uint32_t _main(int argc, char *argv[], uint32_t core_addr)
000000  b570              PUSH     {r4-r6,lr}
;;;12     {
000002  4605              MOV      r5,r0
000004  460e              MOV      r6,r1
000006  4614              MOV      r4,r2
...



В .hex:

:020000042000DA
:1080000070B505460E4614460448046000F05AFA5E

Байты совпадают.

Этап третий. Получаем бинарник.


Лезем в интернет, разбираемся, что же за формат такой .hex:
http://ru.wikipedia.org/wiki/Intel_Hex

Находим спецификацию.

Чтобы перевести .hex в бинарник, воспользуемся вспомогательной программой. В инете они есть, но я предпочел за 5 минут наклепать свою, ибо нужна была уверенность, что все переведется так как мне нужно.
Можете ей воспользоваться на свой страх и риск, но учтите, что она сырая.
(скачать)



Можно заливать на карточку.

Этап четвертый. Собственно, запуск.


// указатель на функцию, с теми же аргументами, что и _main
uint32_t (*program)(int argc, char *argv[], uint32_t core);
...
program = (int(*)(int, char **))0x20008001; 
// Вот тут обратите внимание на адрес. Запускать надо не с 0x...00, а с 0x...01
// Кто может грамотно объяснить почему так, отпишитесь в комментариях. Я это понимаю лишь интуитивно: первая команда
// два байта занимает, а адрес команды, видимо, идет с последнего байта команды.
...
// адрес, куда будем заливать программу
uint8_t *addr;
addr = (uint8_t *)0x20008000;
...
// чтение из файла средствами FatFs
for (j = 0;;)
{
    res = f_read(&prog, buff, sizeof(buff), &br);    
    for(i = 0; i< br; i++)
    {
        addr[i+j] = buff[i];
    }
    j += br;
    if (res || br == 0) break; // error or eof 
}

...
// Собственно, запуск
retval = (*program)(argc-1, argv + 1, (uint32_t)CORE);


Этап пятый. Ядро.


Ну запустили мы какую-то функцию из отдельного файла куда-то в память. И что дальше?
Нам же надо работать с периферией!
Можно опять прикрутить к проекту с программой стандартную периферийную библиотеку и возить с собой уйму платформозависимого кода.

Я предлагаю такое решение. Сделать таблицу с адресами функций, которые будем предоставлять пользовательским программам. Эдакое ядро, что-ли.
Адрес этой таблицы передавать пользовательской программе. Например так:

typedef struct _corefunc
{
		uint16_t	index;
		uint32_t	addr;
		const char	*desc;
} corefunc;


Ну и, для примера, заполним эту табличку:
corefunc CORE[] =
{
	{ 0, (uint32_t)&fputc, "fputc" },
	{ 1, (uint32_t)&LED_GetState, "LED_GetState" },
	{ 2, (uint32_t)&LED_GetBlinkState, "LED_GetBlinkState" },
	{ 3, (uint32_t)&LED_On, "LED_On" },
	{ 4, (uint32_t)&LED_Off, "LED_Off" },
	{ 5, (uint32_t)&LED_OnBlink, "LED_OnBlink" },
	{ 6, (uint32_t)0, "" },
};


В первую очередь передадим программе наше переопределение fputc, чтобы та могла использовать printf для вывода.
Ну и, для разнообразия, добавим подержку светодиодов из моей статьи про USB.

Адрес этой таблички мы уже передали в программу выше (см. uint32_t core_addr)
Теперь надо что-то с этой табличкой сделать.

uint32_t _main(int argc, char *argv[], uint32_t core_addr)
{
	_CORE = (corefunc *)core_addr;
	unwrap_core();
	return _pmain(argc, argv);
}

...

void unwrap_core()
{
    fputc_ = (int(*)(int,FILE *))_CORE[0].addr;	
    LED_GetState_ = (uint8_t (*)(int))_CORE[1].addr;	
...
// и т.д.
}

...

int fputc(int ch, FILE *f)
{
	return (*fputc_)(ch, f);
}

uint8_t LED_GetState(int led)
{
	return (*LED_GetState_)(led);
}

...

// и т.д.






Ну и завершающий штрих — сама программа:

void print_core(void);

int _pmain(int argc, char *argv[])
{
	int i;
	printf("Hello from test program\r\n");
	for(i=0;i<argc;i++)
	{
		printf("Argument %d: %s\r\n", i, argv[i]);
	}

			
	print_core();	

	LED_OnBlink(2, 100, 100);
	return argc;
}

void print_core()
{
	int i;
	printf("Aviable core functions:\r\n");
	for(i=0;_CORE[i].addr != 0 && i<1024;i++)
	{
		printf("%d\t0x%x\t\t\t%s\r\n", _CORE[i].index, _CORE[i].addr, _CORE[i].desc);
	}
}


И небольшой скриншотик:



Велосипед изобретен.

Жду конструктивной и неконструктивной критики, а также обвинения в дилетантстве, в комментариях :)

  • +8
  • 02 октября 2011, 18:42
  • Ezhik
  • 1
Файлы в топике: Hex2ez.zip

Комментарии (89)

RSS свернуть / развернуть
Неплохой изврат. А если взять камень потолще, то на нем можно гигазы мелкого софта подгружать с флешки.
0
Ну да, или как вариант кучу внешнего SRAM, который посредством FSMC мапится в адресное пространство STM32.
Давно уже хочу плату с SRAM сделать, да пока некогда.
Если хотя бы пару мегов прикрутить, то там уже хватит места и на несколько программ, и можно будет подумать о многозадачности…
0
Гран-гран мерси! Вот теперь стало понятно.
Потихоньку задумываюсь над этаким некст-жен спектрумом с СДшкой вместо кассеты и Кортексом вместо Z80. Но пока мне секса хватает, так что оставим эту идею на потом.
Насчет абстракции кода от платформы- в CooCox IDE есть собственная библиотека СОХ, которая и служит посредником между низкоуровневым кодом и логикой программы. Используя ее один и тот же код можно скомпилировать на разные семейства кортексов.
0
Так вроде есть спектрум на FPGA+ARM уже. Еще один? Ну разве что ради самообразования. Или полностью софтовый эмулятор на кортексе? А мощи проца хватит? Сомневаюсь.
0
Напомнило запуск эльфов (*.elf) на мобилках от сименса.
0
  • avatar
  • Resp
  • 02 октября 2011, 19:32
Похожая штука (в виде самопала) есть в сониэриках, сделанных на базе OSE RTOS =) Правда, там честная ОС с честными процессами и API на программных прерываниях.
0
Чтобы перевести .hex в бинарник, воспользуемся вспомогательной программой
В составе binutils есть утилита objcopy, она как раз предназначена для преобразования форматов бинариков. Знает и elf и bin и hex много чего еще. Конвертирует из любого известого ей формата в любой другой. Присутствует в любом тулчейне на основе ГЦЦ.
Было-бы круто таким образом загрузку elf организовать.
0
А как поведет себя эта утилита если ей первой строкой в .hex задать адрес 0x2000xxxx?
0
Можно задать стартовый адрес для выходного бинарика. И даже можно индивидуально задавать смещения для каждой секции, чтоб, например, склеить разрозненные секции в один непрерывный блок.
В общем, полезная вещь, рекомендую изучить.
0
Ура ты выдумал java)))
Там конечно есть потери в производительности но уже все готовенькое.
-1
  • avatar
  • a9d
  • 02 октября 2011, 21:14
Ну если кто-нибудь напишет как запускать java-приложения под STM32, буду очень благодарен.
А еще лучше, .NET Micro Framework :)
0
Вот с этим тяжелее. Java машину уже давно портировали на arm7. Под stm32 скорей всего еще не успели.
0
В том-то и дело :)
А .NET MF портировали :) Только вот мне упорства не хватает, чтобы ее завести на моей плате :)
0
Это не java, это скорее на зачатки однозадачной ОС похоже.

Как там кстати с возможностями управления памятью? Если есть контроллер памяти, то мона и большие бинарники в ОЗУ грузить, подгружая кусками по необходимости.
0
Берешь FreeRTOS прикручиваешь Java. И получается ОС с кучей ограничений. При этом можно будет запускать множество программ одновременно.
0
А, ну с FreeRTOS не интересно :)
Но переключалку процессов оттуда было бы неплохо выдрать :)
0
Там не переключалка процессов интересная. А динамическое создание и удаление процессов.
0
А причем тут жаба-то вообще? Тут что, где-то в байткод компилируют? Умение подгружать и выполнять бинарники — это таки свойство ОС, а не ВМ вроде жабы.
+1
Поставь на арм java машину и получишь тоже самое. Только будет попроще и удобней писать проги. Также будет куда больше возможностей.
0
Java — это VM. Со всеми плюсами (довольно мощный язык, кроссплатформенный бинарный код), но и минусами (высокие требования к памяти и снижение скорости работы в 10-50 раз, т.к. на JIT на МК памяти не хватает).
Это и то, что в статье — мягко говоря, разные категории. И в таком виде, как в статье — это скорее однозадачная ОС, с загрузкой программ извне и API (та самая табличка функций ядра).
0
В этой статье признаков ОС нет. Это обычный загрузчик.
Java на арм работает куда шустрее чем на x86. Но потери в производительности все же будут.
А если скрестить FreeRTOS и Java, то получиться облегченная версия uClinux.
0
Что-то ты ОС и ВМ в кашу мешаешь.
Что ты считаешь за признаки ОС? Да, типичного для встраиваемых РТОС управления задачами тут нет. Но та же DOS тоже была однозадачной и помимо загрузки программ и некоторого API умела только интерфейс пользователя (и тот реализовывался программой). Алсо, признаков жабы тут вообще нет, а на ос хотя бы намек (загрузчик — часть ОС, а тут еще и АПИ).
Java на арм работает куда шустрее чем на x86
С чего бы? Да, на ARM с Jazelle Java испольняется частично аппаратно, но на x86 хватает ресурсов для JIT-трансляции в нативный код, так что проигрыш по производительности составляет процентов 15 по сравнению с хорошо оптимизированным С++, а это весьма и весьма неплохо. В сочетании с более высокой производительностью x86 — ARM-J оно таки ИМХО зарулит. На МК же нет ни Jazelle, ни ресурсов для JIT (в первую очередь ему нужна ОЗУ для хранения оттранслированных кусков кода).
А если скрестить FreeRTOS и Java, то получиться облегченная версия uClinux.
А если скрестить Java и uClinux (вещи это вообще-то ортогональные — OS и VM, которая под ней работает) что получится?)
0
Тогда стоит grub причислить к ОС))
Java при тех же условиях будет работать шустрее на ARM. За счет интеграции java в ядро.

Ясен хер получатся разные продукты но принцип схожий будет как и uClinux.
0
grub — загрузчик ОС. Он не предоставляет API и вообще специфичная для ПК штука. И главное — ОС без grub'а обойдется, а эти прожки — нет, они используют АПИ ядра.

В какое ядро? Jazelle в ARM-J? Оно да, ускорит, хотя солидная часть опкодов все равно выполняется софтово, в исключении. Но на x86 доступна JIT-компиляция, обеспечивающая Яве все то же быстродействие нативного кода.
На ARM-МК же ничего из этого не доступно, JVM будет работать в режиме интерпретации, а это, как известно, в самом лучшем случае 10-15 кратный проигрыш по сравнению с нативным кодом.
0
До ОС этой поделке еще далеко. Даже диспетчера нет.

Работать будет быстрее. Т.к. на кортексах на один 1мгц получаем 1.25 мипса и код находится в памяти МК. О больших процессах говорить смысла нет. Тогда уже проще разобраться с uClinux.
0
Ну зачем же так прям ножом по сердцу :)
Вот пишешь картину, пейзаж какой-нибудь, а тебе «да че это за каляки, возьми лучше цифровой фотоаппарат» :)

Я, конечно, не стал бы эту поделку называть ОС, но что-то не припомню, чтобы в DOS был диспетчер :)
Кстати, последний, может, как-нибудь и напишу.
+1
Флаговый автомат тогда тоже ОС. Grub аналогично. Он может выполнять не только функцию загрузки ОС.
Да и вообще тогда многое можно назвать ОС.
0
И у них тоже есть ядро? :)
0
Вот уж флаговый автомат никак нельзя назвать ОС. Это не более чем механизм распараллеливания задач. Для ОС вообще говоря необязательный — существуют однозадачные ОС.
Grub все же несколько другое. Его можно рассматривать как часть ОС, пусть и выделенную в отдельный проект. Причем эта часть ОС отрабатывает единократно при запуске и дальше не влияет на ее работу, а вот нечто в посте таки предоставляет интерфейс.
0
Ну, во первых, в однозадачных ОС вроде MS-DOS никакого диспетчера не было. ОС есть программа, обеспечивающая взаимодействие пользователя, железа и прикладных программ. HAL'а тут нету (как и в DOS, впрочем), интерфейса пользователя пока тоже (хотя добавить вывод списка программ на SD и запуск выбранной несложно), а вот запуск и поддержка прикладных программ уже есть.

Во вторых, ну 1.25 МИПСа, и что? На современных х86 — уже до 5 DMIPS/MHz, у Core 2 например.
Вот только на ПК памяти много и жабу можно запустить в JIT'е, который минимум на порядок быстрее интерпретатора. А в МК только интерпретатор и влезет. Что, собсно, на примере .net MF и наблюдается.

Ну и в третьих, я не утверждаю что это ОС. Я говорю, что здесь видны зачатки ОС, а вот VM+FW вроде жабы или .net MF и не пахнет.
0
Ну конкретно в статье я не описывал, но вообще, как видно из скриншота, у меня есть командная строка, могу ползать по папкам, смотреть их содержимое и запускать оттуда проги :)
0
О, тем более, это уже вполне себе однозадачная ОС. Особенно если API развит. Скажем, FS хотя бы предоставляет.

Любопытно, однако, что здесь RTOS'ом в основном называют голые диспетчеры потоков (кооперативные или вытесняющие, опционально с средствами синхронизации/общения потоков). Видимо потому, что такие задачи ОС, как интерфейс пользователя (хотя это задача не ОС, а ее оболочки), запуск не-встроенных программ и HAL на МК менее востребованы, чем потоки. Но, тем не менее, система потоков — лишь часть ОС, и есть примеры ОС, ее не имеющие.
0
А если скрестить Java и uClinux
то получится такой себе ucAndroid…
0
Алсо вот зачатки жабы. А не в этой статье.
0
Если Вы имеете ввиду подгружать в те же 32 килобайта (по тому же принципу, что и в DOS грузились проги больше 640кб), то тут по нулям. Но идею можно и развить.
А если про внешнюю память — FSMC + SRAM и вперед.
0
Именно про это.
Яжро ARM7 кстати умело жаловаться на невозможность выборки команды. Этим, вероятно, можно было бы воспользоваться.
0
Сборщик мусора жабы умеет дефрагментировать heap.
0
Жесть. Со времён AVR мечтал о резиновой памяти :)
Жаль конечно что в stm32f100 серии нету FSMC. А то уже руки зачесались написать быдлокода на максимальные 4Гбайта :)
0
на 4г под армы не получится. Максимум только 2г.
0
А где нарыть SRAM на 4Гбайта?
0
А нигде :)
0
Но можно к тому же FSMC подключить NOR/NAND Flash.
0
:) это да, толко вот у NAND'а перезапись ~100000 раз…
0
Это если перезаписывать :)
Можно подрубить NOR с программами и оттуда их грузить, а память внутреннюю юзать.
Правда смысла в этом…
0
Ну почему, исполнять программу из NOR, если она большая, и подгружать данные оттуда же — вполне здравая идея.
0
исполнять программу из NOR
А STM32 умеет исполнять прямо из внейшней NOR? Или нужно в любом случае сначала в RAM скидывать (ну или флэш прошивать)? А то RAM не резиновая у STM32F1xx :(
0
0x60000000-0x9FFFFFFF
External RAM 
Executable region for data

И у этого региона не стоит атрибут XN:

Means the processor prevents instruction accesses. Any 
attempt to fetch an instruction from an XN region causes a 
memory management fault exception.


Так что теоретически можно.
0
Такс… а это не про SRAM идет речь? Извиняюсь за «дилетанизм» в своих вопросах, пока только втягиваюсь в STM32 :)
0
Без разницы, это область памяти для FSMC, а значит из любой подключенной к нему памяти можно загружать инструкции для исполнения. Хоть другой контроллер этой шиной подключи и быстрое межпроцессорное взаимодействие организуй)
0
Блин… взял себе на пробу STM32F107RB — думал на нем попробую, а в нем, как оказалось, FSMC нет :(
0
Так 64 ноги. В даташите открой «pinout and description», там под таблицей написано, что FSMC только в корпусах от 100 ног.
0
Вот я нуб… :) Только сейчас доперло, что FSMC — это не какой-то отдельный интерфейс, а и есть тот самый контроллер внешней памяти. Тогда все понятно становится. Но что-то среди 107-й серии STM32 я FSMC все равно не нашел, даже в «многопиновых» исполнениях. Причем даташит то он качает одинаковый на все 107-е стм-ки.
0
На сайте написано, что это connectivity line, много всяких коммуникационных интерфейсов напихано. FSMC точно есть в 103, 205/207. С буквой V — 100-ногие, Z — 176, кажется. Быстрее всего на compel.ru найти можно, у них сразу ссылки на даташиты лежат.
0
Да, наверное, начну с более «мелкого» 107, который уже заказал. Я купился на USB Host, которого у 103 нет, поэтому приходится расплачиваться отсутствием FSMC и прочего. А там уже видно будет куда дальше копать, если памяти не будет хватать :)
0
PS: что-то не работает у меня «плюсование» и «отнимание» сообщений (рейтинг сообщений) :(
0
Потому что для этого рейтинг выше порога нужен.
0
Понял, спсб.
0
Вот кстати всякие(mega8515 к примеру) AVR это отлично умеют делать.
да и что всегда мешало сделать нечто типа:


int address;
char * p;
address = [ram];
p = (char*)address;
file f;
while(!sd_feof(file))
{
*p = sd_fread(file);
p++;
}

int result2 = (*p) (options);  


кстати подобная идея должна очень хорошо снюхатся с Elm-chan-овой библиотекой FAT.
0
упс, как-то я статью читал через опу
0
Какой DOS. Обычная загрузка оверлея это называется. Ну а до DOS осталась самая малость
Да стандартный загрузчик бы не помешал с динамическим распределением памяти.
STM32 как всегда вкусненькое подбрасывает — спасибо.
0
На счёт таблицы с адресами: в кортексе нет программных прерываний как в x86, что бы системные вызовы делать можно было?
0
А зачем, если можно адрес напрямую грузить?
0
А зачем, если можно адрес напрямую грузить?
Защита. Не нужно таблицу каждому процессу передавать. Либы проще строить. Ну и классика в конце концов.
0
Да, нашел пример. http://www.keil.com/download/docs/357.asp
Действительно, удобно.
0
Есть, SWI называется.
0
Зашибись. Когда-то для x86 ТипаOS писал: с архитектурой разобрался, но понял, что совместимость снизу вверх за лет 15 не осилю — забил. Надо для stm попробовать, может что путное выдет, в любом случае, это будет захватывающе.
0
Чтоб это стало классной ОС, нужны:
1) Фоновые задачи. Как ни крути без фоновых далеко не уедешь.
2) Нужен межпроцессорный обмен и функции синхронизации(мьютексы, секции, события и т.д.)
3) Возможность добавлять свои функции в ядро. Что то наподобие драйверов.
4) Должен быть механизм завершения процесса. Как например Ctrl+C.
5) Ориентация на микросд карточки. Они дешевые.
6) На внешнюю оперативку и большие процессы лучше не замахиваться. Там уже есть uClinux и с ним конкурировать не имеет смысла.

Тем самым это ОС займет свою нишу. Конкурентов у нее не будет.
Для запуска ОС нужен МК+сдкарточка.
0
  • avatar
  • a9d
  • 03 октября 2011, 18:05
И еще нужны функции для сохранения конфигов на сдкарте. Как и в андроиде.
0
1) Фоновая задача=задача оторванная от терминала.
3) А зачем? Предположем, есть прога, которая обрабатывает данные с датчика темп. DS_как_её_там. Т.е нужен 1-Wire. Дать проге интефейс доступа к пинам и таймеру и пускай себе дрыгает. Не нужна? Выгрузить из памяти с дровами вместе. Хотя если таких прог >1 — накладно выходит. Но modprobe/kldload точно не нужен.
4) Опять же, это делает терминал.

P.S: Автору бы +1 поставил.
0
1) Фоновые задачи нужны по любому. Или хотя бы потоки. Иначе в реале эту ОС будет использовать просто ужасно неудобно.
3) Для реализации протоколов. Протоколы лучше сделать на уровне ядра. Тогда не будут проблем с таймингами.
4) Да это делает терминал. Но ОС не должна зависнуть из-за кривого процесса.
0
Прикольно. мне понравилось. Теперь диспетчер задач, менеджер памяти, HAL, сопроцессор (ARM11 c явой), DDR
0
Ага, а потом портировать на него GCC, и круг замкнется :)
А если серьезно, то под такое железо (арм11 с ддр) есть уже ос, ucLinux называется, писать такое самому — слишком дорогим будет ТАКОЙ велосипед.
0
debian на нем уже запускается
0
ЫЫЫ, круто! +1
0
  • avatar
  • _YS_
  • 04 октября 2011, 01:01
И ещё, там маппинг как в x86 есть? Т.е ядро настроило память так, что при обращении к адресу 0xXXXXXXXX идёт обращение к 0xYYYYYYYY.
0
Называется MMU — memory management unit. В CortexM3 нет. Есть как правило в более старших кортексах линейки A.
0
Ezhik для «полного» счастья ИМХО не хватает еще LCD дисплея от мобильника :) — нечто подобное делал еще на 8051, где в качестве RAM использовал кеш-память от 486 (32 или 64 КБ статики на корпус)
0
program = (int(*)(int, char **))0x20008001; 
// Вот тут обратите внимание на адрес. Запускать надо не с 0x...00, а с 0x...01
// Кто может грамотно объяснить почему так, отпишитесь в комментариях. Я это понимаю лишь интуитивно: первая команда
// два байта занимает, а адрес команды, видимо, идет с последнего байта команды.
Это признак кода Thumb-режима. Посмотрите об этом в инете.
как вариант можно почитать в спеке на отечественный контроллер.
milandr.ru/uploads/Products/product_80/spec_seriya_1986BE9x.rar

кстати они обещали 144 ногий 100МГц АРМ М3 за 160 руб =)
0
О, спасибо!
0
О, спасибо!

А с приемкой «5» сколько будет стоить?
0
Приемка «5» вроде около 3-4тыс.
0
Вроде подороже. Если Вам нужна приёмка, то у Вас должен быть ПЗ и всё оттуда вытекающее =)
0
Недавно у миландровцев на семинаре в Екатеринбурге спрашивали. Была озвучена такая цифра.
0
Ну на самом деле вполне приемлемая цена за 5ю приемку.
0
Спасибо за пост. А использовать внешнюю ОЗУ есть опыт? Если да — поделитесь пожалуйста, удачи!
0
Пока нет. В перспективе планирую, но, видимо, не скоро.
0
Скорость выполнения кода из ram не будет ниже?
0
The Code, SRAM, and external RAM regions can hold programs. However, it is 
recommended that programs always use the Code region. This is because the processor 
has separate buses that enable instruction fetches and data accesses to occur 
simultaneously. 
0
А как можно сделать функцию для размещения в ОЗУ в IDE IAR? Я не смог найти там операций с памятью. Кто-нибудь пробовал?
0
  • avatar
  • Alm
  • 15 апреля 2017, 22:45
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.