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

 
 
4 страниц V   1 2 3 > »   
Reply to this topicStart new topic
> STM3210X_LD_VL, табличная инициализация периферии
_Pasha
сообщение Jan 26 2013, 11:15
Сообщение #1


;
******

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



Привет.
Озадачился сабжем на мелкие армы.
От простого к сложному, сделал такую штуку.
Прикрепленный файл  batch_conf.zip ( 1.52 килобайт ) Кол-во скачиваний: 71

Обновляю здесь, пока есть возможность редактировать.
пример использования
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;


Разницы на коротких кусках практически нет. Т.е. смысл только в тотальном использовании такого метода с исключением вычислений этапа выполнения. Утоптать конфигуратор, конечно, можно.
А также к байт-коду перейти.

Сообщение отредактировал _Pasha - Jan 26 2013, 16:27
Go to the top of the page
 
+Quote Post
Tahoe
сообщение Jan 26 2013, 12:51
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 459
Регистрация: 30-03-06
Из: Москва
Пользователь №: 15 600



Цитата(_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.

И что будем делать? Сэкономим пару байт на инициализации и повесим снаружи железо, как они "советуют"?
Go to the top of the page
 
+Quote Post
HHIMERA
сообщение Jan 26 2013, 13:03
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 226
Регистрация: 10-07-09
Пользователь №: 51 126



Цитата(_Pasha @ Jan 26 2013, 15:15) *
От простого к сложному, сделал такую штуку.

ИМХО - пустая трата времени...
Разве что... "Существуют ещё и градации серого." (С)
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Jan 26 2013, 13:32
Сообщение #4


;
******

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



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

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

Вы в ответ на частное решение начали сыпать частностями, но из другой области sm.gif Да у Вас в самый худенький F100 не больше двух вменяемых драйверов влезет sm.gif а еще и что-то делать нужно. Более того, еще со времен ассемблера всегда старался таблично железо настраивать.
Да и какая сложность, обернете batch_conf() с местно заданной табличкой в xxxx_Init() ? Единственный критерий - либо память либо скорость, хоть что-то должно быть на высоте. В общем, сущность уже есть, кривая она или не очень - каждый решает сам.

Сообщение отредактировал _Pasha - Jan 26 2013, 13:33
Go to the top of the page
 
+Quote Post
ReAl
сообщение Jan 26 2013, 14:01
Сообщение #5


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Подобным образом (парами адрес-данные в собираемой линкером табличке) какой-то из многочисленных компиляторов i51 набирал инициализацию переменных. Т.е. там все переменные шли в одну секцию, без разбора .data/.idata/.bss/.ibss (даже не в одну секцию, а просто "в память"), на старте чистилась нулями вся оперативка, а потом из таблички заносились не нули. Что интересно, по сравнению с более привычным разделением на секции и копированием двух массивов в .data и .idata, на мелких программах даже выигрыш был.

Кстати, о секциях. Почему бы не набирать инициализирующую таблицу в специальной секции, приблизительно как тут набирается информация о прилинкованных модулях. Будет каждый модуль енсти с собой свою информацию (чего не любил, «ещё со времён ассемблера»™, так это централизованной инициализации чем-то в духе __low_level_init() в одном месте на всю программу).


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Jan 26 2013, 14:12
Сообщение #6


;
******

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



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

А есть места, там где надо! Типа write-once периферии, даже есть в железе нет возможности лочить(благо, в сабже есть кое-где), то хоть приблизиться к счастью sm.gif

Сообщение отредактировал _Pasha - Jan 26 2013, 14:14
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Jan 26 2013, 14:13
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



Народ а можно в 2 словах в чем бизнес то? За что боремся то?
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Jan 26 2013, 14:17
Сообщение #8


;
******

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



Цитата(Golikov A. @ Jan 26 2013, 18:13) *
Народ а можно в 2 словах в чем бизнес то? За что боремся то?

Я пытаюсь понять остроту необходимости в маленькой виртуальной машинке для худеньких камешков
Go to the top of the page
 
+Quote Post
ReAl
сообщение Jan 26 2013, 14:20
Сообщение #9


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



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


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Jan 26 2013, 14:35
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



что то я видать отстал от технологий...

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

в какой момент настанет экономия?
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Jan 26 2013, 14:45
Сообщение #11


;
******

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



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

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

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

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

Вот это как раз и выясняю. Попробовать в законченном девайсе, станет ясно.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jan 26 2013, 14:53
Сообщение #12


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(_Pasha @ Jan 26 2013, 20:45) *
За что Паскаль и люблю.

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


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Jan 26 2013, 14:58
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



не я правда что-то не втыкаюsad.gif

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

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

RCC->CR |= RCC_CR_PLLON;


во флэше как и во время выполнения после оптимизации имхо одно и тоже количество инструкций или я чего то не понимаю?
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Jan 26 2013, 15:26
Сообщение #14


;
******

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



Цитата(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() остальной антураж - чтобы не ронять удобство обращения.
---
Конечно, самое оно - код переменной длины заделать. Тогда точно памяти меньше будет нужно.
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Jan 26 2013, 15:32
Сообщение #15


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



sad.gif чет я все равно не понимаю...

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

такое чувство что все знаю что-то что мне не известноsm.gif.... и очевидно.
Go to the top of the page
 
+Quote Post

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

 


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


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