Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: STM3210X_LD_VL
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
_Pasha
Привет.
Озадачился сабжем на мелкие армы.
От простого к сложному, сделал такую штуку.
Нажмите для просмотра прикрепленного файла
Обновляю здесь, пока есть возможность редактировать.
пример использования
CODE

#include "batch_conf.h"
batch_BEGIN(main_tbl)
batch_OR(&(RCC->CR),RCC_CR_HSEON)
batch_WAIT(&(RCC->CR), RCC_CR_HSERDY)
batch_WRITE(&(RCC->CFGR),RCC_CFGR_PLLMULL_0 |RCC_CFGR_PLLSRC)
batch_OR(&(RCC->CR), RCC_CR_PLLON)
batch_WAIT(&(RCC->CR), RCC_CR_PLLRDY)
batch_OR(&(RCC->CFGR),2)
batch_END;

batch_conf(main_tbl, NULL);



Создается таблица во флеше.
Элемент - структура {uint32_t port, data;} Названия полей многоцелевые, поэтому чисто условные, можно unionom разделить для ясности
В тетраду бит 24-27 поля port встроена команда
Конфигуратор выполняет эти команды

Функция заняла 316 байт в кейле.
фрагмент, соответствующий примеру
CODE
RCC->CR |= RCC_CR_HSEON;
while(!(RCC->CR & RCC_CR_HSERDY));
RCC->CFGR = RCC_CFGR_PLLMULL_0 |RCC_CFGR_PLLSRC ;
RCC->CR |= RCC_CR_PLLON;
while(!(RCC->CR & RCC_CR_PLLRDY));
RCC->CFGR |= 2;


Разницы на коротких кусках практически нет. Т.е. смысл только в тотальном использовании такого метода с исключением вычислений этапа выполнения. Утоптать конфигуратор, конечно, можно.
А также к байт-коду перейти.
Tahoe
Цитата(_Pasha @ Jan 26 2013, 15:15) *
Создается таблица во флеше.

1. Насколько я понимаю, сразу после того, как адреса периферии будут помещены в таблицу, они перестанут быть volatile. С потенциально возможными приколами и последствиями.
2. А как потом сопровождать эту помойку?
3. И главное. Как писать драйвера, с учетом этого "веяния"? Т.е. вместо DEV_X_DRV.h, где вызывается инициализация, например, пинов, все поубивать? А как быть, если пин расшарен и требует в разные моменты разной инициализации/конфигурации?

"Не экономь память. Память, это г*вно. Производительность!" (с) Один умный человек, еще лет 10-12 назад сказал мне.


P.S.
А если попадётся вот такой, тяжелый случай, когда производитель свинью подложил, вместо SPI, снова менять концепцию инициализации периферии?

CODE
////////////////////////////////////////////////////////////////////////////////
// TRF7960_X_drv.h //////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
#ifndef TRF7960_X_DRV_H
#define TRF7960_X_DRV_H

////////////////////////////////////////////////////////////////////////////////
#include <bsp.h>

////////////////////////////////////////////////////////////////////////////////
typedef BSP_U08 TRF796x_U08;
typedef BSP_U16 TRF796x_U16;
typedef BSP_U32 TRF796x_U32;
typedef BSP_BOOL TRF796x_BOOL;
typedef BSP_U08 TRF796x_DATA;

////////////////////////////////////////////////////////////////////////////////
#define TRF796x_X_Init() BspTrf796x_Init()
#define TRF796x_X_Enable() BspTrf796x_Enable()
#define TRF796x_X_Disable() BspTrf796x_Disable()
#define TRF796x_X_IrqEnable() BspTrf796x_InterruptEnable()
#define TRF796x_X_IrqDisable() BspTrf796x_InterruptDisable()
#define TRF796x_X_TimerConfig( U08 ) BspTrf796x_TimerConfig( U08 )
#define TRF796x_X_TimerStart() BspTrf796x_TimerStart()
#define TRF796x_X_TimerStop() BspTrf796x_TimerStop()
#define TRF796x_X_Delay_mSec( U32 ) BspDelay_mSec( U32 )

#define TRF796x_DUMMY 0x00

////////////////////////////////////////////////////////////////////////////////
#pragma inline
void TRF796x_X_Command( const TRF796x_U08 Command )
{
// SLOA155 - TRF7960A Firmware Design Hints
// 7.7 SPI With SS Pin Only – Single-Byte Direct Commands
// Description
// All single byte direct commands need an additional CLK cycle to work.
// Workaround
// All direct command functions need to have an additional DATA_CLK cycle
// before Slave Select l line goes high.

BspSpiOpen();
BspSpiXfer08_Mode00( Command );
BspSpiXfer08_Mode00( TRF796x_DUMMY );
BspSpiClose();
}

////////////////////////////////////////////////////////////////////////////////
#pragma inline
TRF796x_U08 TRF796x_X_Read( const TRF796x_U08 Addr )
{
TRF796x_U08 Data;

////////////////////////////////////////////////////////////////////////////
BspSpiOpen();
BspSpiXfer08_Mode00( Addr );
Data = BspSpiXfer08_Mode01( TRF796x_DUMMY );
BspSpiClose();

return( Data );
}

////////////////////////////////////////////////////////////////////////////////
#pragma inline
void TRF796x_X_ReadBurst( const TRF796x_U08 Addr,
TRF796x_U08 * pData,
TRF796x_U08 Count )
{
BspSpiOpen();
BspSpiXfer08_Mode00( Addr );
while( Count-- )
{
*pData++ = BspSpiXfer08_Mode01( TRF796x_DUMMY );
}
BspSpiClose();
}

////////////////////////////////////////////////////////////////////////////////
#pragma inline
void TRF796x_X_Write( const TRF796x_U08 Addr,
const TRF796x_U08 Data )
{
////////////////////////////////////////////////////////////////////////////
BspSpiOpen();
BspSpiXfer08_Mode00( Addr );
BspSpiXfer08_Mode00( Data );
BspSpiClose();
}

////////////////////////////////////////////////////////////////////////////////
#pragma inline
void TRF796x_X_WriteBurst( const TRF796x_U08 Addr,
TRF796x_U08 * pData,
TRF796x_U08 Count )
{
// SLOA155 - TRF7960A Firmware Design Hints
// 7.2 SPI With SS Pin Only – Direct Commands
// Description
// Serial interface with SS pin only, the direct commands are not executed
// if they are the last operation in the SPI communication. In the SPI interface
// with SS pin the Stop condition clock pulse is missing (compared to
// the parallel interface and SPI without SS pin). Some operations are relying
// on this clock and they do not work as expected.
// Workaround
// If a direct command is the last operation in the SPI communication,
// the SS pin goes high. Afterward, an additional clock pulse has to be sent.

BspSpiOpen();
BspSpiXfer08_Mode00( Addr );
while( Count-- )
{
BspSpiXfer08_Mode00( *pData++ );
}
BspSpiClose();
BspSpiXfer08_Mode00( TRF796x_DUMMY );
}

#endif //TRF7960_X_DRV_H

В данном случае, проблема вот в этом:
Цитата
7.1 SPI With SS Pin Only – No High Impedance

Description
Serial interface with SS pin only, the interface does not go to high impedance when SS is high. It is not
possible to multiplex the serial port interface lines.

Workaround
An external three-state buffer must be used if the chip is connected to a serial bus and the interface lines
are multiplexed.

И что будем делать? Сэкономим пару байт на инициализации и повесим снаружи железо, как они "советуют"?
HHIMERA
Цитата(_Pasha @ Jan 26 2013, 15:15) *
От простого к сложному, сделал такую штуку.

ИМХО - пустая трата времени...
Разве что... "Существуют ещё и градации серого." (С)
_Pasha
Цитата(Tahoe @ Jan 26 2013, 16:51) *
1. Насколько я понимаю, сразу после того, как адреса периферии будут помещены в таблицу, они перестанут быть volatile. С потенциально возможными приколами и последствиями.

Спасибо. Дельное замечание. Поправлю.
Цитата
...
И что будем делать? Сэкономим пару байт на инициализации

Вы в ответ на частное решение начали сыпать частностями, но из другой области sm.gif Да у Вас в самый худенький F100 не больше двух вменяемых драйверов влезет sm.gif а еще и что-то делать нужно. Более того, еще со времен ассемблера всегда старался таблично железо настраивать.
Да и какая сложность, обернете batch_conf() с местно заданной табличкой в xxxx_Init() ? Единственный критерий - либо память либо скорость, хоть что-то должно быть на высоте. В общем, сущность уже есть, кривая она или не очень - каждый решает сам.
ReAl
Подобным образом (парами адрес-данные в собираемой линкером табличке) какой-то из многочисленных компиляторов i51 набирал инициализацию переменных. Т.е. там все переменные шли в одну секцию, без разбора .data/.idata/.bss/.ibss (даже не в одну секцию, а просто "в память"), на старте чистилась нулями вся оперативка, а потом из таблички заносились не нули. Что интересно, по сравнению с более привычным разделением на секции и копированием двух массивов в .data и .idata, на мелких программах даже выигрыш был.

Кстати, о секциях. Почему бы не набирать инициализирующую таблицу в специальной секции, приблизительно как тут набирается информация о прилинкованных модулях. Будет каждый модуль енсти с собой свою информацию (чего не любил, «ещё со времён ассемблера»™, так это централизованной инициализации чем-то в духе __low_level_init() в одном месте на всю программу).
_Pasha
Цитата(ReAl @ Jan 26 2013, 18:01) *
(чего не любил, «ещё со времён ассемблера»™, так это централизованной инициализации чем-то в духе __low_level_init() в одном месте на всю программу).

А есть места, там где надо! Типа write-once периферии, даже есть в железе нет возможности лочить(благо, в сабже есть кое-где), то хоть приблизиться к счастью sm.gif
Golikov A.
Народ а можно в 2 словах в чем бизнес то? За что боремся то?
_Pasha
Цитата(Golikov A. @ Jan 26 2013, 18:13) *
Народ а можно в 2 словах в чем бизнес то? За что боремся то?

Я пытаюсь понять остроту необходимости в маленькой виртуальной машинке для худеньких камешков
ReAl
Цитата(_Pasha @ Jan 26 2013, 16:12) *
А есть места, там где надо! Типа write-once периферии, даже есть в железе нет возможности лочить(благо, в сабже есть кое-где), то хоть приблизиться к счастью sm.gif
А чем «одно место», собранное вручную в функцию __low_level_init() красивее «одного места», собранного линкером и выполненного на нужном этапе (до старта main, до выполнения конструкторов, etc.)?
Ну порядок инициализации — проще управлять в «одном одном месте» (хотя никто не мешает и по подсекциям собирать с «приоритетоами»).
Зато имеем «добавил модуль — добавилось автоматически его одно место», нет шанса забыть в low_level_init() что-то добавить.
Golikov A.
что то я видать отстал от технологий...

я вообще не понимаю генеральной целиsm.gif...

в какой момент настанет экономия?
_Pasha
Цитата(ReAl @ Jan 26 2013, 18:20) *
Зато имеем «добавил модуль — добавилось автоматически его одно место», нет шанса забыть в low_level_init() что-то добавить.

За что Паскаль и люблю.
По теме - конфигуратор-то как раз допускает и так и эдак инициализацию, хоть в одном хоть по требованию, разумеется, если это не 1 бит поменять.
Я неспроста все время вопрос и применимости только в LD_VL, потому что для остальных по-любому стараюсь писать так, чтобы, например, скорости передачи uart, вычисляло само, исходя из имеющегося клока. Чтобы настроить DMA-самостоятельно, карту что его куда пусть решает в рантайме, на входе адрес периферии и адрес буфера.Тем более, при инлайнах цена вопроса почти 0.00

Жалко, что без темплейтов тип параметра не определишь, не хочется плюсов все еще.
Итд, быстроты особой не нужно.

Цитата(Golikov A. @ Jan 26 2013, 18:35) *
какой момент настанет экономия?

Вот это как раз и выясняю. Попробовать в законченном девайсе, станет ясно.
AHTOXA
Цитата(_Pasha @ Jan 26 2013, 20:45) *
За что Паскаль и люблю.

+1:)
Хотя сейчас в gcc вроде бы есть __attribute__((constructor)).
Что касаемо самой идеи, то я тоже за то, чтоб инициализация была помодульно.
Ещё одно замечание - таким макаром получается сугубо линейная инициализация. То есть, например, не получится (?) при сбое инициализации HSE откатиться на HSI.
Golikov A.
не я правда что-то не втыкаюsad.gif

почему
batch_OR(&(RCC->CR),RCC_CR_PLLON)

будет в чем то лучше

RCC->CR |= RCC_CR_PLLON;


во флэше как и во время выполнения после оптимизации имхо одно и тоже количество инструкций или я чего то не понимаю?
_Pasha
Цитата(AHTOXA @ Jan 26 2013, 18:53) *
+1:)
Хотя сейчас в gcc вроде бы есть __attribute__((constructor)).
Что касаемо самой идеи, то я тоже за то, чтоб инициализация была помодульно.
Ещё одно замечание - таким макаром получается сугубо линейная инициализация. То есть, например, не получится (?) при сбое инициализации HSE откатиться на HSI.


Нелинейные участки за счет вызова функций по указателю например batch_CALL0(func,arg) - дальнейшая инициализация отменяется, если ф-ция вернула 0.

Цитата(Golikov A. @ Jan 26 2013, 18:58) *
во флэше как и во время выполнения после оптимизации имхо одно и тоже количество инструкций или я чего то не понимаю?

Выигрыш должен пойти при частой переинициализации указателей и загрузке непосредственных данных, также при энном кол-ве while() остальной антураж - чтобы не ронять удобство обращения.
---
Конечно, самое оно - код переменной длины заделать. Тогда точно памяти меньше будет нужно.
Golikov A.
sad.gif чет я все равно не понимаю...

это для систем в которых меняется прошивка на лету что ли?

такое чувство что все знаю что-то что мне не известноsm.gif.... и очевидно.
_Pasha
Цитата(AHTOXA @ Jan 26 2013, 17:53) *
То есть, например, не получится (?) при сбое инициализации HSE откатиться на HSI.

В продолжение. Таки надо, чтобы batch_conf() был не void, а int
чтобы информацию об откате выдавать на-гора. Добавлю.
kolobok0
Цитата(Golikov A. @ Jan 26 2013, 19:32) *
...такое чувство что все знаю что-то что мне не известноsm.gif.... и очевидно.


просветление это!
пора в индию к ламам sm.gif))
scifi
Цитата(Tahoe @ Jan 26 2013, 16:51) *
"Не экономь память. Память, это г*вно. Производительность!" (с) Один умный человек, еще лет 10-12 назад сказал мне.

На самом деле это сказал Дональд Кнут, причём несколько иначе: производительность тоже говно, главное - читаемость кода.
Golikov A.
Цитата(kolobok0 @ Jan 26 2013, 21:12) *
просветление это!
пора в индию к ламам sm.gif))


Так может просветите? Как и зачем автор собирается использовать спец функцию которая ухудшает читабельность? Наверное правильнее сказать записывает другими словами те же действия?
AHTOXA
Цитата(Golikov A. @ Jan 27 2013, 00:25) *
Так может просветите? Как и зачем автор собирается использовать спец функцию которая ухудшает читабельность?

Автор предлагает заменить запись REG=VALUE;, которая обычно компилируется в нечто типа
Код
movw    r1, low(REG)
movt    r1, high(REG)
movw    r2, low(VALUE)
movt    r2, high(VALUE)
str r2, [r1, #0]
на два слова - адрес регистра и значение. Плюс подпрограмма, получающая массив пар регистр-значение, и записывающая значения по адресам. (Я немного упростил)
При больших объёмах инициализации это должно дать выигрыш по объёму кода. (Это - цель)
HHIMERA
Цитата(AHTOXA @ Jan 26 2013, 21:52) *
Плюс подпрограмма, получающая массив пар регистр-значение, и записывающая значения по адресам. (Я немного упростил)

Мы лицезреем рождение очередной ардуины... 05.gif
Цитата
При больших объёмах инициализации это должно дать выигрыш по объёму кода. (Это - цель)

В Low Density??? И что в остатке???
Golikov A.
Цитата(AHTOXA @ Jan 26 2013, 22:52) *
Автор предлагает заменить запись REG=VALUE;, которая обычно компилируется в нечто типа
Код
movw    r1, low(REG)
movt    r1, high(REG)
movw    r2, low(VALUE)
movt    r2, high(VALUE)
str r2, [r1, #0]
на два слова - адрес регистра и значение. Плюс подпрограмма, получающая массив пар регистр-значение, и записывающая значения по адресам. (Я немного упростил)
При больших объёмах инициализации это должно дать выигрыш по объёму кода. (Это - цель)


а ну слава богу значит идею я в целом понял верно. Теперь у меня вопрос, какой процент кода занимает инициализация?
AHTOXA
Цитата(Golikov A. @ Jan 27 2013, 01:26) *
Теперь у меня вопрос, какой процент кода занимает инициализация?

На STM3210X_LD_VL? Очень большой. Периферии куча, а памяти с гулькин нос. Поэтому здесь путь такой - всё, что только возможно, делается аппаратно. Соответственно, инициализация - основная часть программы.
На таких чипах обычно кроме инициализации больше почти ничего и не делаютsm.gif
Golikov A.
Цитата(AHTOXA @ Jan 26 2013, 23:39) *
На STM3210X_LD_VL? Очень большой. Периферии куча, а памяти с гулькин нос. Поэтому здесь путь такой - всё, что только возможно, делается аппаратно. Соответственно, инициализация - основная часть программы.
На таких чипах обычно кроме инициализации больше почти ничего и не делаютsm.gif



а не получиться ли так что передать 2 слова + место занятое этими 2 словами в функцию записи данных в регистр будет больше чем просто записать данные в регистр пятью командами?

поглядел доку на семейство, там самое мелкое значение флешки 64 кБайта, не такая уж у гули маленькая писяsm.gif.... Не если конечно подрубать чужие библиотеки не глядя все улетит сразу, но если ручками, то этого дофига... ИМХО
_Pasha
Цитата(Golikov A. @ Jan 26 2013, 22:25) *
Так может просветите? Как и зачем автор собирается использовать спец функцию которая ухудшает читабельность? Наверное правильнее сказать записывает другими словами те же действия?

Попутно узрел еще одну перспективу. Дело в том, что если я на птичьем языке буду описывать действия, относящиеся к инициализации, а их немного, будет проще перейти на переменную длину псевдокоманд, поскольку для него нужна тулза, собирающая коллекцию адресов, данных и масок и формирующая их массив, который не будет более 256 элементов, типа словаря в архивном файле. Естественно, завязываться на Си-синтаксис никто не будет. А так - красота. Кстати, COG кто-нить пользует?

Цитата(Golikov A. @ Jan 27 2013, 00:14) *
а не получиться ли так что передать 2 слова + место занятое этими 2 словами в функцию записи данных в регистр будет больше чем просто записать данные в регистр пятью командами?

Сейчас выигрыш небольшой, скачайте посмотрите. Но я только сегодня этим позанимался.
AHTOXA
Цитата(Golikov A. @ Jan 27 2013, 02:14) *
а не получиться ли так что передать 2 слова + место занятое этими 2 словами

Нет, не получится. Потому что передавать надо не два слова, а адрес массива слов.

Цитата(_Pasha @ Jan 27 2013, 02:16) *
будет проще перейти на переменную длину псевдокоманд

А какие проблемы с переменной длиной? Ну вот, навскидку:
0 - команда очистки, 1 параметр(адрес);
1 - команда записи, 2 параметра (адрес, значение);
2 - команда установки битов, 2 параметра (адрес, маска);
...
25 - команда ожидания установки битов, 3 параметра (адрес, маска, тайм-аут);
...
команды - как влезет, думаю, что байта за глаза хватит. Выравнивание вот только полетит, но это ничего, мы ж за плотность боремсяsm.gif
ReAl
Цитата(Golikov A. @ Jan 26 2013, 22:14) *
а не получиться ли так что передать 2 слова + место занятое этими 2 словами в функцию записи данных в регистр будет больше чем просто записать данные в регистр пятью командами?
В функцию эти два слова не передаются сами по себе. Они все записываются в массив структур. Функция берёт массив и выбирате/выполняет.
Приблизительно как
Код
switch(cmd) {
case cm_a: cm_a_func(); break;
case cm_b: cm_b_func(); break;
case cm_c: cm_c_func(); break;
case cm_d: cm_d_func(); break;
}
и
Код
struct {
    uint8_t cmd;
    void (*pfunc)(void);
} cmdtable[] = {
    {cm_a, cm_a_func},
    {cm_b, cm_b_func},
    {cm_c, cm_c_func},
    {cm_d, cm_d_func},
    {0, 0}
};
плюс функция поиска в массиве по полю cmd с вызовом функции по полю pfunc.
На больших таблицах функций выигрыш ощутимый. Либо при большом количестве таких switch() -- функция поиска в таблице-то одна на всех.

В данном случае (при 316 байтах в интерпретаторе) выигрыш в коде при тупой записи в регистры пойдёт где-то после 26..27-ой пары, при операциях типа |= где-то после 20-той, при wait-операциях — после 16-той. Надо уменьшать интерпретатор :-)
Ради такого дела можно и на асме выписать :-)

Цитата(AHTOXA @ Jan 26 2013, 22:23) *
0 - команда очистки, 1 параметр(адрес);
И ещё команда записи 1-ки (вместе с командой записи 0 полезны для bit-band области).
Ну и подэкономить можно на вариации аргумента для записи uint8_t/uint16_t/uint32_t. Только это все интерпретатор утолщает, дольше ждать, когда прибыль пойдёт.

Цитата(AHTOXA @ Jan 26 2013, 22:23) *
Выравнивание вот только полетит, но это ничего, мы ж за плотность боремсяsm.gif
А у CM0 обращение по невыровненному бывает? А то ведь это имеет смысл для мелких кристаллов.
Golikov A.
кажется начинаю понимать...

а сколько операций уходить на запись данных в регистр этой функцией? Что то у меня на запись регистра меньше не выходит, сэкономить можно на загрузке старшей части регистра адреса но....
_Pasha
Цитата(AHTOXA @ Jan 27 2013, 00:23) *
Ну вот, навскидку:
0 - команда очистки, 1 параметр(адрес);
Выравнивание вот только полетит, но это ничего, мы ж за плотность боремсяsm.gif

Очистка как раз используется раз в 100лет sm.gif
Выравнивание при том, что никуда не спешим, значения не имеет.
Установка битов, кстати, операции |= &= есть, а ^= еще нету, добавлю.
Можно влезть в байт при другой псевдомашине, но уже с регистровой моделью, типа
регистры адреса источника, приёмника, непосредственных данных, таймаута, адреса вспомогательной функции. Но сейчас конфигуратор влезает в 304 или 308 байт, а там - уже хз.
А с внешней тулзой
uint32_t sfr_collection[]={тратата}; и также коллекция масок и прочая. И будут байты при простой машине.

Golikov A.
Цитата(ReAl @ Jan 27 2013, 00:37) *
А у CM0 обращение по невыровненному бывает? А то ведь это имеет смысл для мелких кристаллов.


опять перестал понимать%(

выборка из памяти без выравнивания у кортекса 3 только, а во флеше все равно с выравниванием. а У 0 и память и флеш с выравниванием. Может внешнюю флэшку легче подрубить?
AHTOXA
Цитата(ReAl @ Jan 27 2013, 02:37) *
И ещё команда записи 1-ки (вместе с командой записи 0 полезны для bit-band области).
Ну и подэкономить можно на вариации аргумента для записи uint8_t/uint16_t/uint32_t. Только это все интерпретатор утолщает, дольше ждать, когда прибыль пойдёт.

Да, тут так сразу не угадаешьsm.gif Думаю, после пары-тройки байтовых команд уже будет выигрыш от спец-варианта.

Цитата(ReAl @ Jan 27 2013, 02:37) *
А у CM0 обращение по невыровненному бывает? А то ведь это имеет смысл для мелких кристаллов.

STM3210X_LD_VL - это M3 всё же. Да и вообще, Паша утоптал команду в адрес (я написал, а потом таки удосужился скачать и посмотреть предмет обсуждения :-) )
_Pasha
Цитата(ReAl @ Jan 27 2013, 00:37) *
Надо уменьшать интерпретатор :-)
Ради такого дела можно и на асме выписать :-)

Или switch заменить на массив меток, привязамшись к GCC sm.gif
Или просто лишние сущности выкинуть: чтение из порта и запись в переменную по указателю и по дескриптору, уже легче станет.
ps
Физика жанра:
вот я сейчас пишу одну штучку, дык там надо вначале по ресету твердо назначить некоторые пины в неактивное состояние, чтобы не бросать силовой модуль, потом уже строить клоки, потом вернуться к пинам, кой-чего переключить на ацп, потом слегка протестировать окружающую обстановку, а потом еще раз вернуться к пинам а закончить инит. Пока пишу традиционно, чтобы иметь отправную точку.
Golikov A.
Хоть плачьsm.gif...


стандартный вариант
в регистр записывается адрес
в регистр записываются данные
сохраняются данные по адресу

интерпритаторый варинат
выбирается команда-адрес
выбираются данные

проводиться декодировка команды и вызов функции сохранения данных по адресу

сохраняются данные по адресу

декодировка - это одна функция ее не считаем, это постоянная издержка которая размажется на кучу команд и пропадет.

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

чего я не понимаюsm.gif?
AHTOXA
Цитата(Golikov A. @ Jan 27 2013, 02:55) *
чего я не понимаюsm.gif?

Того, что интерпретаторный вариант делается в цикле, он один на всю прошивку.
Golikov A.
код команды грузить же все равно надо?
данные грузить все равно же надо?

или играют на том что для короткого кода команды можно за одну загрузку несколько команд считать?
_Pasha
Цитата(Golikov A. @ Jan 27 2013, 00:04) *
код команды грузить же все равно надо?
данные грузить все равно же надо?

или играют на том что для короткого кода команды можно за одну загрузку несколько команд считать?

А Вы еще забыли про настройку адреса и stubs.
А в сабже стубов нету! yeah.gif
Golikov A.
Можете расписать что происходит при записи допустим 3 регистров. Я правда очень хочу понять...

_Pasha
Цитата(Golikov A. @ Jan 27 2013, 00:15) *
Можете расписать что происходит при записи допустим 3 регистров. Я правда очень хочу понять...

Не пойму, применительно к сабжу?
непонимание, оказывается, заразно. sm.gif
Golikov A.
ну да естественно как виртуальная машина обрабатывает 3 записи в регистр.
естественно схематично
_Pasha
Выбрали запись.
Декодировали команду >>24 &0x0F
Сделали нужные преобразования типов - храним варианты: волатильный адрес, и данные - либо непосредственные либо это указатель.
Дальше switch на допустимые команды
Дальше инкремент указателя и заново.

Условие останова - равенство нулю поля, в которое зашита команда, т.к. это адрес периферии, заведомо не нуль.
Остальное можно почитать из текста в первом посте.
Golikov A.
ну все я понял в чем маза.

это короче разница такая же как между

int arr[3];

arr[0]=0;
arr[1]=1;
arr[2]=2;

и

for(int i=0;i<3;i++)
arr[i] = i;



Спасибо за интересный опыт. Чет я правда долго втыкал в фактически очевидные вещи... wink.gif
_Pasha
Цитата(Golikov A. @ Jan 27 2013, 01:44) *
Спасибо за интересный опыт.

Пожалуйста. Но это только начало. Топтать этих два uint32_t нужно обязательно, к вечеру уже домедитировался я sm.gif
Только без внешних средств это невозможно, иначе текст превратится в новояз, из которого совсем ничего не понятно.
Golikov A.
Один раз вспоминается был проект где надо было сильно уменьшить код, правда для передачи по в то время медленным линиям связи
В проце был написан разархиватор зип, поскольку алгоритм разархивирования известен, на компьютере прошивку архивировали зипом, слали, там она распаковывалась и работала.

Фактически вы делаете тоже самое, так что может имеет смысл не придумывать свой РИСК язык, а тупо заархивировать нормальный бинарик, а на проце его распаковывать и выполнять?
_Pasha
Цитата(Golikov A. @ Jan 27 2013, 02:08) *
Фактически вы делаете тоже самое, так что может имеет смысл не придумывать свой РИСК язык, а тупо заархивировать нормальный бинарик, а на проце его распаковывать и выполнять?

К нему еще памяти оверлейной надо отъесть из ОЗУ. Тоже как-то... и кучей ничего не сделаешь, потому что относительных переходов не будет... тупо фиксированный буфер. Идея хорошая, но как-то не знаю пока.
Golikov A.
если упростить архиватор, и скармливать ему линейные куски кода, то вполне возможно.

ну тогда я бы написал "компилятор", который в препроцесинге превращал бы читаемый сишный код, в ваш сокращенный, иначе это реально будет адsm.gif, особенно если сделаете команды переменной длинны
_Pasha
Цитата(Golikov A. @ Jan 27 2013, 03:42) *
если упростить архиватор, и скармливать ему линейные куски кода, то вполне возможно.

Можно действительно напихать предлагаемые мною таблицы в секцию, затем ее выгрузить, удалить, запаковать RLE и загрузить обратно
Только с указателями сложно. Придется данные по ним получать последовательным доступом. Сразу ка:кбы отпадает желание где-то таблично перестраивать железо. В работе-то уже надо быстро это делать... Да собственно, чего тут бояццо, наверное это самый ReAl'ный sm.gif путь. Не зря пообщались.
HHIMERA
Цитата(_Pasha @ Jan 27 2013, 04:50) *
В работе-то уже надо быстро это делать...

Вот и я о том... Как-то "быстро" и "упаковка/распаковка" не очень то стыкуется...
Тем более, что LD_VL не настолько уж быстра...
"Здесь обрезали - там пришили"(С)

Цитата
наверное это самый ReAl'ный sm.gif путь.

Лучше бы он был мате'ReAl'ный biggrin.gif
AlexandrY
Цитата(_Pasha @ Jan 26 2013, 13:15) *
От простого к сложному, сделал такую штуку.


Забавно смотрится такой фрагмент:
Код
            do{
                case bcmd_Wait_MSK:
                    result = 1;
                    continue;
                case bcmd_Wait_nMSK:
                    result = 0;
                    continue;
            }while(0);


Это чтобы goto не использовать?
Мощно, я бы даже сказал "идеологично". biggrin.gif
_Pasha
Цитата(HHIMERA @ Jan 27 2013, 13:10) *
Лучше бы он был мате'ReAl'ный biggrin.gif

Подражание кетайсам laughing.gif если получится вялосепет с дешевыми квадратными колесами, будет Ы.

Цитата(AlexandrY @ Jan 27 2013, 13:46) *
Мощно, я бы даже сказал "идеологично". biggrin.gif

Дык это со знакомства с прототредами такое не пугает sm.gif а даже наоборот. Вообще с этим do{}while(0) столько красивых выефокусов, что всегда притягиват.
khach
Обычно в одном куске кода работаем с одной периферией. Может в заголовке (первой строке массива команд) хранить базовый адрес для устройства 32 битный, а команды содержат только оффсет от базового адреса? Тогда каждая команда "утопчется" в 32 бита. Конечно, прогрузку 32 разрядного регистра константой прийдется делать на две команды.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.