Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Организация программ
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
Страницы: 1, 2
Zelepuk
Планируется разработка измерительного прибора, принимающего данные от АЦП в прерывании, складывающего данные в буфер и обрабатывающего данные пос ложному алгоритму.
Дело в том что нужно часто давать сигналы готовности данных на разных ступенях алгоритма. Использовать флаги - глобальные переменные неудобно (их будет слишком много).
Сообщить, какие "более красивые подходы" для этого используются.
например на микрокотнтроллере можно использовать ОСРВ и ее средства взаимодействия между задачами, а как быть когда нужно сделать демо-проект на PC (для последующего переноса на МК)?

Например есть такая задача:
1)АЦП складывает данные непрерывно в кольцевой буфер
2) Раз в миллисекунду данные из буфера обрабатываются результат сохраняется в переменную.
3) после 10й итерации по пункту 2 (т.е. раз в 10 миллисекунд) нужно делать усреднение данных

У меня сейчас в функции, которая реализует п.2 просто есть счетчик итераций в виде переменной. Я опрашиваю эту переменную, и, как только она равна 10 - запускаю функию, реализующую п.3
Все это выглядит ужасно в бесконечном цикле.

Подскажите, как сделать грамотно.
ViKo
Я понял так, программа делает то, что от нее требуется. Кому какое дело, как она устроена? Кроме разработчика,желающего сделать красиво. Так и сделайте, как считаете. Сравните. Переделайте еще 5 раз. Нормальный процесс.
Zelepuk
Цитата(ViKo @ Mar 31 2017, 11:19) *
Я понял так, программа делает то, что от нее требуется. Кому какое дело, как она устроена? Кроме разработчика,желающего сделать красиво. Так и сделайте, как считаете. Сравните. Переделайте еще 5 раз. Нормальный процесс.

Эт понятно. мне интересно как можно считать. На уме был только суперлуп... sad.gif но есть понимание что тогда прога будет изобиловать глобальными переменными.
Я про подходы говорю. Интересно как можно сделать. Вот статья в тему интересная: https://habrahabr.ru/post/148805/

Я вот например хочу сделать на FreeRTOS, но как тогда удобно сделать чтобы проект запустился и на PC. На PC запускаю для демонстрационных целей.
jcxz
Цитата(Zelepuk @ Mar 31 2017, 09:52) *
У меня сейчас в функции, которая реализует п.2 просто есть счетчик итераций в виде переменной. Я опрашиваю эту переменную, и, как только она равна 10 - запускаю функию, реализующую п.3
Подскажите, как сделать грамотно.

В ISR, который пишет данные в буфер, смотреть сколько данных накопилось в буфере, и если их больше чем сколько-то - посылать сообщение в майл-бокс.
А под ОС есть задача, которая ждёт на этом мэйл-боксе, и получив сообщение, запускается, читает и обрабатывает данные из буфера, до его опустошения. Потом снова идёт на ожидание мэйл-бокса. Это классический подход к реализации задач обработки событий под ОС. И в том числе цикл обработки сообщений винды (основной рабочий цикл любой GUI-программы) так работает.
И все задачи работающие с данными из периферии (или генерящие туда данные) у меня так построены.
AlexandrY
Цитата(Zelepuk @ Mar 31 2017, 11:24) *
Эт понятно. мне интересно как можно считать. На уме был только суперлуп... sad.gif но есть понимание что тогда прога будет изобиловать глобальными переменными.
Я про подходы говорю. Интересно как можно сделать. Вот статья в тему интересная: https://habrahabr.ru/post/148805/

Я вот например хочу сделать на FreeRTOS, но как тогда удобно сделать чтобы проект запустился и на PC. На PC запускаю для демонстрационных целей.

FreeRTOS не лучший выбор. Я бы рекомендовал Micrium OS
Гораздо быстрее, понятнее и компактнее чем FreeRTOS. Там кстати очень ценная фишка для риалтайма появилась - работа сервисов без запрещения прерываний.

Глобальные флаги не так плохи как кажется.
Когда у вас появится больше 5-и источников прерываний по 1 мс и около десятка задач, просто чтобы поддерживать все необходимые интерфейсы как вот здесь:
Нажмите для просмотра прикрепленного файла
и когда использование процессора подойдет к 80%, то вы быстро поймете, что стоит вместо сервисов RTOS использовать глобальные флаги или иначе потеряете реальное время.

Хороший способ - это критичные прерывания сделать прерываниями ядра, и чтобы они выставляли глобальные флаги и софтварно прерывания с сервисами RTOS.
Это очень эффективный способ прореживания прерываний PendSV и укорачивания времени выполнения остальных прерываний.

Но на PC вы это не перенесете, это все очень архитектурно привязано к железу.
Риалтайм в принципе не отладить на PC.
jcxz
Цитата(AlexandrY @ Mar 31 2017, 11:09) *
FreeRTOS не лучший выбор. Я бы рекомендовал Micrium OS
Гораздо быстрее, понятнее и компактнее чем FreeRTOS.

Поддерживаю! rolleyes.gif

Цитата(AlexandrY @ Mar 31 2017, 11:09) *
Но на PC вы это не перенесете, это все очень архитектурно привязано к железу.
Риалтайм в принципе не отладить на PC.

Перенести можно, если разделить на middle-ware и собственно low level IO с периферией.
Сам делал и отлаживал так когда сложный драйвер. Из железа ему нужен был только IO с UART.
Так что нижний уровень драйвера на МК - это был IO в/из кольцевых буферов в ISR-ах, а на PC - в те же самые буфера в/из файловых функций WinAPI + система сообщений к задаче обработке - мэйл-боксы под Микриум, и соотв. средства синхронизации под винду. Основной код драйвера - выполнялся в виде задачи обработки событий, которая была общая для Win и для Микриум. Очень удобно было отлаживать. Там 95% всего объёма составляло это middle-ware.
Да собственно так же организована FatFS. Её тоже можно выполнять под любой ОС хоть под виндой. Написав простую low level IO прослойку.
Lagman
Цитата(AlexandrY @ Mar 31 2017, 12:09) *
Я бы рекомендовал Micrium OS

Цитата(jcxz @ Mar 31 2017, 12:23) *
Поддерживаю! rolleyes.gif

Эх, была бы она бесплатная, хотя бы как раньше, купил книгу и используй как хочешь. Хотя после того как micrium был куплен Silicon Labs может и бесплатно уже распространяется?
XVR
2 ТС - какой у вас целевой процессор и ресурсы? Если они позволяют развернуться с RTOS и всем, что к ней прилагается (в самом общем смысле), то можно взять что нибудь, что работает и под РС тоже (eCos непример) и написать на ней. Получите то, что хотите - и РС для отладки и МК в качестве конечной цели.
Если же с ресурсвми на МК не густо, то перенос чего либо с РС на МК дело непростое - проще сделать слой совместимости и писать поверх него (как вам тут уже советовали). Но это дополнительная работа (и может быть очень не малая sad.gif )

Есть промежуточный подход - выделить из задачи блоки, напрямую не зависищие от аппаратуры, написать их отдельными модулями и сделать для них unit тесты (для отладки)
Тогда большую (или меньшую, если не повезет sm.gif ) часть можно будет отладить на РС, но собирать это все в кучу придется на МК (и run time взаимодествие между модулями тоже придется делать на МК)
AlexandrY
Цитата(jcxz @ Mar 31 2017, 12:23) *
Перенести можно, если разделить на middle-ware и собственно low level IO с периферией.

Micrium OS с самого рождения имела порт по Windows.
А нынче у нее под Windows выполняется всё: файловая, сетевые стеки, GUI, USB
Весь список виден в Micrium Platform Builder.

Но риалтайм ( т.е. как быстро обрабатываются задачи и прерывания и как расходуются ресурсы процессора) это отладить не помогает.

На PC я отлаживаю исключительно сторонние программные модули с неизвестным потреблением памяти.
Все остальное не оправдано, поскольку такие IDE как IAR с SWD компилируют и загружают на целевую платформу почти с такой же скоростью как и в Visual Studio под Windows
jcxz
Цитата(AlexandrY @ Mar 31 2017, 12:20) *
Все остальное не оправдано, поскольку такие IDE как IAR с SWD компилируют и загружают на целевую платформу почти с такой же скоростью как и в Visual Studio под Windows

Это да, но под виндой лучше дело с логгированием и сохранением разных отладочных данных (есть файловая система для этого). И это сохранение практически не влияет на работу отлаживаемого кода.
AlexandrY
Цитата(Lagman @ Mar 31 2017, 12:42) *
Эх, была бы она бесплатная, хотя бы как раньше, купил книгу и используй как хочешь. Хотя после того как micrium был куплен Silicon Labs может и бесплатно уже распространяется?

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

Цитата(jcxz @ Mar 31 2017, 13:24) *
Это да, но под виндой лучше дело с логгированием и сохранением разных отладочных данных (есть файловая система для этого). И это сохранение практически не влияет на работу отлаживаемого кода.

RTT через SWD логгирует с той же скоростью и также может писать в файлы.
Но главное эти логи можно оставить в релизной версии.
Т.е. сорсы не приходится править и захламлять условными препроцессорными директивами.

Кстати вот как я тестировал FatFS на целевой платформе - https://geektimes.ru/post/274416/
Ну зачем мне там нужно было бы делать это на PC?
Zelepuk
Цитата(jcxz @ Mar 31 2017, 11:52) *
В ISR, который пишет данные в буфер, смотреть сколько данных накопилось в буфере, и если их больше чем сколько-то - посылать сообщение в майл-бокс.
А под ОС есть задача, которая ждёт на этом мэйл-боксе...

Вот вопрос как это делается, где почитать/посмотреть/скачать пример этого...

Цитата(AlexandrY @ Mar 31 2017, 13:20) *
Но риалтайм ( т.е. как быстро обрабатываются задачи и прерывания и как расходуются ресурсы процессора) это отладить не помогает.

Собственно на PC не нужно отлаживать реалтайм, на PC нужно показать как все это работает. Например вместо считывания данных в прерывании считывать данные из файла.
Вопрос только как именно это сделать, если на мк есть прерывание и функциа типа ISR_ADC(), то на PC(в консольном приложении) как имитировать периодический вызов функции чтения из файла?
AlexandrY
Цитата(Zelepuk @ Mar 31 2017, 15:12) *
как имитировать периодический вызов функции чтения из файла?

В Micrium OS есть эмулятор контроллера прерываний.
Задаете там через специальные функции интервал срабатывания и указываете callback функции для обработки прерываний.
В тех функциях стандартно пользуетесь API Windows для чтение из файлов сервисами RTOS для передачи флагов. И все.
Zelepuk
Micrium платный. да еще за IAR платить надо.

Проще тогда наверное Keil с его ОС использовать. Хоть только за Keil платить придется...
jcxz
Цитата(Zelepuk @ Mar 31 2017, 14:12) *
Вот вопрос как это делается, где почитать/посмотреть/скачать пример этого...

Что делается? Я вроде описал всё. Документация по конкретным функциям есть в исходниках uCOS.
syoma
Zelepuk, а не хотите попробовать Matlab/Simulink/Embedded Coder под это дело? Ваша задача выглядит типовой для этого.
Т.е. всю обработку данных и свои алгоритмы нарисовать в Simulink в виде модели, которую вы сможете моделировать на PC вместе с входными данными, а затем всю модель выгрузить за несколько кликов в Си код, который будет исполняться в реальном времени на вашем контроллере. И все это без морок с глобальными флагами и переменными и часто даже без ОСРВ. Это достаточно "красивый" подход с заделом на будущее. Называется Model-Based Design.
ViKo
Цитата(Zelepuk @ Mar 31 2017, 15:54) *
Проще тогда наверное Keil с его ОС использовать. Хоть только за Keil платить придется...

Да, Keil - это благо. И ОС там легкая.
Zelepuk
Цитата(syoma @ Mar 31 2017, 16:22) *
Zelepuk, а не хотите попробовать Matlab/Simulink/Embedded Coder под это дело? Ваша задача выглядит типовой для этого.
Т.е. всю обработку данных и свои алгоритмы нарисовать в Simulink в виде модели, которую вы сможете моделировать на PC вместе с входными данными, а затем всю модель выгрузить за несколько кликов в Си код, который будет исполняться в реальном времени на вашем контроллере. И все это без морок с глобальными флагами и переменными и часто даже без ОСРВ. Это достаточно "красивый" подход с заделом на будущее. Называется Model-Based Design.

Почем-то мне думается что там не все так просто и красиво как описывается. посмотреть бы пример реализации такого подхода. Генерируемый код весьма труден для понимания. Увидеть бы готовый вариант простой процедуры: принять байт от SPI, накопить буфер, посчитать среднее раз в 100мс.
syoma
Цитата
Генерируемый код весьма труден для понимания.

Его не надо читать и понимать. Достаточно знать, что он делает то же самое, что и в симуляции.
Цитата
принять байт от SPI, накопить буфер, посчитать среднее раз в 100мс.

Вопрос - сколько байт надо накопить за 100мс? или как часто приходят новые данные?
jcxz
Цитата(Zelepuk @ Mar 31 2017, 15:47) *
Почем-то мне думается что там не все так просто и красиво как описывается. посмотреть бы пример реализации такого подхода. Генерируемый код весьма труден для понимания. Увидеть бы готовый вариант простой процедуры: принять байт от SPI, накопить буфер, посчитать среднее раз в 100мс.

Что там трудного?:
CODE
void MboxPost(OS_EVENT *mbox)
{
int e = OSMboxPost(mbox, (void *)1);
if (e != OS_ERR_NONE && e != OS_ERR_MBOX_FULL) trap(TRAP_OS, e);
}
void MboxPend(OS_EVENT *mbox)
{
u8 e;
OSMboxPend(mbox, 0, &e);
if (e != OS_ERR_NONE) trap(TRAP_OS, e);
}
isr() {
if (PERIPH.EMPTY) return;
t1 = sysTimer;
do { //Вычитываем все байты из FIFO периферии в программный FIFO.
uint i = PERIPH.READ;
if (!FIFO.isFull()) FIFO.write(i);
} while (!PERIPH.EMPTY);
if (FIFO.cnt() < N) if ((uint)(sysTimer - t1) < (uint)T) return; //Смотрим если в программном FIFO накопилось менее чем N байт (FIFO.cnt) и прошло менее чем T мсек с момента t1, то return;
иначе:
IsrEnter();
MboxPost(mbox); //посылаем сообщение сервисному процессу обработать накопленный программный FIFO.
IsrExit();
}
__noreturn void Task(void *) { //сервисный процесс, обслуживающий программный FIFO
t1 = sysTimer;
while (1) {
while (!FIFO.isEmpty()) {
FIFO.read();
...
}
MboxPend(mbox);
}
}

Всё. Это для uCOS. Для других ОС примерно так же.
Zelepuk
Цитата(syoma @ Mar 31 2017, 17:19) *
Его не надо читать и понимать. Достаточно знать, что он делает то же самое, что и в симуляции.

Вопрос - сколько байт надо накопить за 100мс? или как часто приходят новые данные?

примерно 50кБ.

Lagman
Цитата(AlexandrY @ Mar 31 2017, 13:28) *
Бесплатная то она бесплатная, но мне только через 2 месяца пришел ответ типа извините мы были перегружены запросами, хотим продолжить общение.
И на очередной запрос опять зависли.

Посмотрите сами, она бесплатна только для некоммерческого применения за все остальное надо платить. https://www.micrium.com/buy/licensing/
AlexandrY
Цитата(syoma @ Mar 31 2017, 16:22) *
Т.е. всю обработку данных и свои алгоритмы нарисовать в Simulink в виде модели, которую вы сможете моделировать на PC вместе с входными данными, а затем всю модель выгрузить за несколько кликов в Си код, который будет исполняться в реальном времени на вашем контроллере.

Оч интересно, а каким таким образом Simulink вдруг гарантирует нам выполнение в реальном времени?
Или вы реальным временем обзываете все что только способно выполняться в микроконтроллере? biggrin.gif

Цитата(Lagman @ Mar 31 2017, 18:13) *
Посмотрите сами, она бесплатна только для некоммерческого применения за все остальное надо платить. https://www.micrium.com/buy/licensing/

Ну если вам так хочется делать бизнес и никому не платить, что поделаешь? Проходите мимо. laughing.gif
Lagman
Цитата(AlexandrY @ Mar 31 2017, 18:26) *
Ну если вам так хочется делать бизнес и никому не платить, что поделаешь? Проходите мимо. laughing.gif

Вы сами то поняли на что ответили? Я ее как раз и не стал использовать, только потому, что она очень дорого выходит для штучных коммерческих изделий.
syoma
Цитата(Zelepuk @ Mar 31 2017, 16:33) *
примерно 50кБ.

Если считать, что принять байт от SPI, накопить буфер, - это делает Ваш драйвер SPI, а сама процедура посчитать среднее вызывается раз в 100мс, и ей передается массив из 50000 значений, то в Симулинке она будет выглядеть так:
Нажмите для просмотра прикрепленного файла
Рассчитано для исходного типа int8, результата суммы int32.
Тогда сгенерированный код будет выглядеть вот так:
ert_main.c - функция main
CODE
/*
/*
* File: ert_main.c
*
* Code generated for Simulink model 'Average'.
*
* Model version : 1.39
* Simulink Coder version : 8.11 (R2016b) 25-Aug-2016
* C/C++ source code generated on : Fri Mar 31 21:32:35 2017
*
* Target selection: ert.tlc
* Embedded hardware selection: 32-bit Generic
* Code generation objectives: Unspecified
* Validation result: Not run
*/

#include <stddef.h>
#include <stdio.h> /* This ert_main.c example uses printf/fflush */
#include "Average.h" /* Model's header file */
#include "rtwtypes.h"

static RT_MODEL_Average_T Average_M_;
static RT_MODEL_Average_T *const Average_M = &Average_M_;/* Real-time model */

/* '<Root>/In1' */
static int8_T Average_U_In1[50000];

/* '<Root>/Out1' */
static int8_T Average_Y_Out1;

/*
* Associating rt_OneStep with a real-time clock or interrupt service routine
* is what makes the generated code "real-time". The function rt_OneStep is
* always associated with the base rate of the model. Subrates are managed
* by the base rate from inside the generated code. Enabling/disabling
* interrupts and floating point context switches are target specific. This
* example code indicates where these should take place relative to executing
* the generated code step function. Overrun behavior should be tailored to
* your application needs. This example simply sets an error status in the
* real-time model and returns from rt_OneStep.
*/
void rt_OneStep(RT_MODEL_Average_T *const Average_M);
void rt_OneStep(RT_MODEL_Average_T *const Average_M)
{
static boolean_T OverrunFlag = false;

/* Disable interrupts here */

/* Check for overrun */
if (OverrunFlag) {
return;
}

OverrunFlag = true;

/* Save FPU context here (if necessary) */
/* Re-enable timer or interrupt here */
/* Set model inputs here */

/* Step the model */
Average_step(Average_M, Average_U_In1, &Average_Y_Out1);

/* Get model outputs here */

/* Indicate task complete */
OverrunFlag = false;

/* Disable interrupts here */
/* Restore FPU context here (if necessary) */
/* Enable interrupts here */
}

/*
* The example "main" function illustrates what is required by your
* application code to initialize, execute, and terminate the generated code.
* Attaching rt_OneStep to a real-time clock is target specific. This example
* illustrates how you do this relative to initializing the model.
*/
int_T main(int_T argc, const char *argv[])
{
/* Unused arguments */
(void)(argc);
(void)(argv);

/* Pack model data into RTM */

/* Initialize model */
Average_initialize(Average_M, Average_U_In1, &Average_Y_Out1);

/* Attach rt_OneStep to a timer or interrupt service routine with
* period 0.1 seconds (the model's base sample time) here. The
* call syntax for rt_OneStep is
*
* rt_OneStep(Average_M);
*/
printf("Warning: The simulation will run forever. "
"Generated ERT main won't simulate model step behavior. "
"To change this behavior select the 'MAT-file logging' option.\n");
fflush((NULL));
while (((void*) 0) == (NULL)) {
/* Perform other application tasks here */
}

/* The option 'Remove error status field in real-time model data structure'
* is selected, therefore the following code does not need to execute.
*/
#if 0

/* Disable rt_OneStep() here */

/* Terminate model */
Average_terminate(Average_M);

#endif

return 0;
}

/*
* File trailer for generated code.
*
* [EOF]
*/



Функция average - собственно сам расчет среднего
CODE
/*
* File: Average.c
*
* Code generated for Simulink model 'Average'.
*
* Model version : 1.39
* Simulink Coder version : 8.11 (R2016b) 25-Aug-2016
* C/C++ source code generated on : Fri Mar 31 21:22:13 2017
*
* Target selection: ert.tlc
* Embedded hardware selection: 32-bit Generic
* Code generation objectives: Unspecified
* Validation result: Not run
*/

#include "Average.h"
#include "Average_private.h"

void mul_wide_s32(int32_T in0, int32_T in1, uint32_T *ptrOutBitsHi, uint32_T
*ptrOutBitsLo)
{
uint32_T absIn0;
uint32_T absIn1;
uint32_T in0Lo;
uint32_T in0Hi;
uint32_T in1Hi;
uint32_T productHiLo;
uint32_T productLoHi;
absIn0 = in0 < 0 ? ~(uint32_T)in0 + 1U : (uint32_T)in0;
absIn1 = in1 < 0 ? ~(uint32_T)in1 + 1U : (uint32_T)in1;
in0Hi = absIn0 >> 16U;
in0Lo = absIn0 & 65535U;
in1Hi = absIn1 >> 16U;
absIn0 = absIn1 & 65535U;
productHiLo = in0Hi * absIn0;
productLoHi = in0Lo * in1Hi;
absIn0 *= in0Lo;
absIn1 = 0U;
in0Lo = (productLoHi << /*MW:OvBitwiseOk*/ 16U) + /*MW:OvCarryOk*/ absIn0;
if (in0Lo < absIn0) {
absIn1 = 1U;
}

absIn0 = in0Lo;
in0Lo += /*MW:OvCarryOk*/ productHiLo << /*MW:OvBitwiseOk*/ 16U;
if (in0Lo < absIn0) {
absIn1++;
}

absIn0 = (((productLoHi >> 16U) + (productHiLo >> 16U)) + in0Hi * in1Hi) +
absIn1;
if (!((in0 == 0) || ((in1 == 0) || ((in0 > 0) == (in1 > 0))))) {
absIn0 = ~absIn0;
in0Lo = ~in0Lo;
in0Lo++;
if (in0Lo == 0U) {
absIn0++;
}
}

*ptrOutBitsHi = absIn0;
*ptrOutBitsLo = in0Lo;
}

int32_T mul_s32_hiSR(int32_T a, int32_T b, uint32_T aShift)
{
uint32_T u32_chi;
uint32_T u32_clo;
mul_wide_s32(a, b, &u32_chi, &u32_clo);
return (int32_T)u32_chi >> aShift;
}

/* Model step function */
void Average_step(RT_MODEL_Average_T *const Average_M, int8_T Average_U_In1
[50000], int8_T *Average_Y_Out1)
{
int32_T i;
int32_T rtb_SumofElements;

/* Sum: '<S1>/Sum of Elements' incorporates:
* Inport: '<Root>/In1'
*/
rtb_SumofElements = Average_U_In1[0];
for (i = 0; i < 49999; i++) {
rtb_SumofElements += Average_U_In1[i + 1];
}

/* End of Sum: '<S1>/Sum of Elements' */

/* Outport: '<Root>/Out1' incorporates:
* Gain: '<S1>/Gain'
*/
*Average_Y_Out1 = (int8_T)mul_s32_hiSR(351843721, rtb_SumofElements, 12U);
UNUSED_PARAMETER(Average_M);
}

/* Model initialize function */
void Average_initialize(RT_MODEL_Average_T *const Average_M, int8_T
Average_U_In1[50000], int8_T *Average_Y_Out1)
{
/* Registration code */

/* external inputs */
(void)memset(&Average_U_In1[0], 0, 50000U * sizeof(int8_T));

/* external outputs */
(*Average_Y_Out1) = 0;
UNUSED_PARAMETER(Average_M);
}

/* Model terminate function */
void Average_terminate(RT_MODEL_Average_T *const Average_M)
{
/* (no terminate code required) */
UNUSED_PARAMETER(Average_M);
}

/*
* File trailer for generated code.
*
* [EOF]
*/


По коду можно сказать, что матлаб сгенерировал хитрый умножитель на 1/50000. Почему - это зависит от того, что поддерживает, а что нет конкретная платформа

Цитата
Оч интересно, а каким таким образом Simulink вдруг гарантирует нам выполнение в реальном времени?

Посмотрите первый комментарий в первом из сгенерированных файлов.
AlexandrY
Цитата(syoma @ Mar 31 2017, 22:31) *
Посмотрите первый комментарий в первом из сгенерированных файлов.

Цитата
Associating rt_OneStep with a real-time clock or interrupt service routine is what makes the generated code "real-time".

Они над вами смеются. Заметили скобочки?
Прочитайте весь комментарий.
Они оставляют за собой право сделать "Overrun" и посылают вас самих это расхлебывать.
Причем флаг "Overrun" оставили статическим внутри функции. Феерично!
Так что не надо нам этих фэйков. biggrin.gif
Цитата(Lagman @ Mar 31 2017, 19:16) *
Я ее как раз и не стал использовать, только потому, что она очень дорого выходит для штучных коммерческих изделий.

Не знаю, я делаю штучные и коммерческие, я мэйкер. Мне бесплатно.
syoma
Цитата(AlexandrY @ Mar 31 2017, 22:17) *
Они оставляют за собой право сделать "Overrun" и посылают вас самих это расхлебывать.

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

Цитата
Причем флаг "Overrun" оставили статическим внутри функции. Феерично!

А в чем проблема?
rt_OneStep в примере предлагается вызывать в прерывании от таймера.
Во время исполнения модельного кода флаг Overrun ставится в true, а после завершения сбрасывается. Если следующее прерывание от таймера произойдет до окончания исполнения модельного кода, факт overrun ловится и делай, сам, что считаешь нужным.
Вообще-то ert_main.c - это всего лишь пример, как можно запустить функцию на исполнение в реальном времени без ОСРВ. Его можно без проблем изменять по своему усмотрению.
AlexandrY
Цитата(syoma @ Mar 31 2017, 23:26) *
А как вы предлагаете расхлебывать ситуацию в реальном времени, если разработанная вами функция не выполнится за заданное время?

Никак, в Simulink вы её не расхлебаете и даже не узнаете о ней.
Симулинк будет тупо раз за разом перезаписывать свои заглушки поверх ваших правок.
Его код предназначен для устойчивой среды исполнения на базе RTOS уже сделанной в микроконтроллере.

Вы же так и делаете. Используете vxWorks, а тут подсовываете надуманную лабуду.
syoma
Цитата(AlexandrY @ Mar 31 2017, 22:37) *
Симулинк будет тупо раз за разом перезаписывать свои заглушки поверх ваших правок.

Не понимаю я вас. Где и что Симулинк будет перезаписывать?
Lagman
Цитата(AlexandrY @ Mar 31 2017, 23:19) *
Не знаю, я делаю штучные и коммерческие, я мэйкер. Мне бесплатно.

Это ваше оправдание, можете жить спокойно, только не заглядывайте на страничку о покупке microc os и не читайте про лицензии.
TigerSHARC
Интересно сравнить, где "красивше" будет реализация такой нехитрой задачи:
прерывание вызывается раз в 1мс, после десяти прерываний необходимо вызвать функцию, после десяти вызовов функции вызвать другую функцию.

с while(1), все понятно: заводим 2 глобальных счетчика и вперед щелкать инкременты в прерывании.
С RTOS нешто проще как-то?
Lagman
Цитата(TigerSHARC @ Apr 3 2017, 21:11) *
Интересно сравнить, где "красивше" будет реализация такой нехитрой задачи:
прерывание вызывается раз в 1мс, после десяти прерываний необходимо вызвать функцию, после десяти вызовов функции вызвать другую функцию.

с while(1), все понятно: заводим 2 глобальных счетчика и вперед щелкать инкременты в прерывании.
С RTOS нешто проще как-то?

Как вы собираетесь вызывать через 10 прерываний функцию? Если без ОСРВ то при вызове функции из прерывания вы будет находиться так же в прерывании, если не придумаете другой механизм вызова этой функции. Если с ОСРВ то будет то же самое (только вне прерывания) после 10 инкрементов в прерывании будет передано (например сообщение для вашей функции которая уже будет называться задачей и ожидать это сообщение) сообщение и если приоритет этой задачи (вашей функции) будет главным то по выходу из прерывания, планировщик переключит выполнение программы на эту функцию.
Но вся эта магия приобретает интерес когда у вас будет несколько параллельных задач, например обработка АЦП в реальном времени (цифровая фильтрация), передача параметров по modbus и вывод значений на экран.
Zelepuk
Цитата(Lagman @ Apr 3 2017, 22:49) *
Как вы собираетесь вызывать через 10 прерываний функцию? Если без ОСРВ то при вызове функции из прерывания вы будет находиться так же в прерывании


Зачем в прерывании вызывать функцию? обычно в прерывании дергаем флаг, а в цикле while(1) опрашиваем его.
Baser
Цитата(Zelepuk @ Apr 4 2017, 09:20) *
Зачем в прерывании вызывать функцию? обычно в прерывании дергаем флаг, а в цикле while(1) опрашиваем его.

Ну так и говорят, что "супер луп" с циклом while(1) и прерываниями будет хорошо работать только тогда, когда нет других многочисленных задач, которые также обслуживаются в основном цикле. Если других задач нет, время между взведением флага в прерывании и обработкой в главном цикле мало и почти детерминировано. Иначе это время сильно плавает и может выходить за допустимые рамки, и тогда алгоритм будет рушиться. Приоритет то у всех задач главного цикла одинаковый.

А вот при наличии вытесняющей RTOS можно гибко настраивать приоритеты задач и время до обработки вашего "флага" будет более определенным.
Lagman
Добавлю к словам Baser'a
Цитата(Zelepuk @ Apr 4 2017, 09:20) *
Зачем в прерывании вызывать функцию? обычно в прерывании дергаем флаг, а в цикле while(1) опрашиваем его.

Что бы реакция МК была приближена к "мгновенной реакции", в ОСРВ это называется время реакции системы.
А так можно все делать и без ОСРВ только это будет тяжелей поддерживать и координировать взаимосвязь и время работы "функций" в вашей программе.
HardEgor
Цитата(Zelepuk @ Apr 4 2017, 13:20) *
Зачем в прерывании вызывать функцию? обычно в прерывании дергаем флаг, а в цикле while(1) опрашиваем его.

Тут стоит соблюдать баланс - какие-то обработки можно и в прерывании делать, а что-то передать в основной цикл. Вопрос приоритетности подзадач обрабатывающих поступающие и отдаваемые данные.
TigerSHARC
Цитата(Lagman @ Apr 4 2017, 14:00) *
Добавлю к словам Baser'a

Что бы реакция МК была приближена к "мгновенной реакции", в ОСРВ это называется время реакции системы.
А так можно все делать и без ОСРВ только это будет тяжелей поддерживать и координировать взаимосвязь и время работы "функций" в вашей программе.

Вы предлагаете прерывании обрабатывать данные или что?
Мгновенная реакция - это конечно здорово, если нужно, например битик выставить в регистр, но FFT вы тоже считать в прерывании будете? sm.gif
AlexandrY
Цитата(TigerSHARC @ Apr 4 2017, 22:00) *
Мгновенная реакция - это конечно здорово, если нужно, например битик выставить в регистр, но FFT вы тоже считать в прерывании будете? sm.gif

Да, именно в прерывании очень удобно делать FFT.
Поскольку длительность всех прерываний автоматически логится SWO трассером и ведется статитстика.
В системах жесткого реального времени самое важное - это профайлинг, а не RTOS, прерывания или что-то еще.
А тут вы профайлинг получаете не пошевелив даже пальцем .

У любого ARM-а есть туча свободных векторов прерываний и есть достаточное количество приоритетов у прерываний.
Так что делать FFT в прерываниях я бы даже рекомендовал.

Под RTOS типа Micrium OS такая концепция отлично ложится.
Они кстати сегодня разослали предложение скачать триальную версию на 45 дней с Micrium Platform Builder.
Lagman
Цитата(TigerSHARC @ Apr 4 2017, 22:00) *
Мгновенная реакция - это конечно здорово, если нужно, например битик выставить в регистр, но FFT вы тоже считать в прерывании будете? sm.gif

А что вы так боитесь этого прерываний, это та же функция (ведь у вас ОС нет, которая может зависнуть в этот момент а есть голый микроконтроллер) которая будет вызываться в определенный момент, откладывая все остальные функции, а как закончится итерация вычисления FFT функция выйдет из обработчика и дальше ваши функции продолжат выполняться.
Make_Pic
Решил не создавать новую тему, а здесь спросить:

Никогда не пользовался setjmp/longjmp для сохранения под Cortex M3,4 контекста - возможно ли сделать так же красиво, как по ссылке:
setjmp/longjmp AVR
Хотелось, если можно с примером кода (различие AVR/ARM).
Или как в простой AVR-ской CoOS (файл в приложении) использование setjmp/longjmp:
Какие компиляторы под ARM Cortex M3,4, GNU GCC, IAR... переваривают такое?
jcxz
Цитата(Make_Pic @ Apr 5 2017, 12:58) *
Никогда не пользовался setjmp/longjmp для сохранения под Cortex M3,4 контекста - возможно ли сделать так же красиво, как по ссылке:

Сохранение/восстановление контекста делают все вытесняющие ОС. Возьмите Cortex-порт от любой и посмотрите.
Make_Pic
Цитата(jcxz @ Apr 6 2017, 00:02) *
Сохранение/восстановление контекста делают все вытесняющие ОС. Возьмите Cortex-порт от любой и посмотрите.

Спасибо! За смотрите туда, не знаю куда... Я конкретно спросил про использование/помощь здесь, а не рыться в исходниках Осов, тосов, ртосов. Что я уже делал.
bve
Из Вашего обработчика вызовите свободное прерывание с нужным приоритетом.
k155la3
Цитата(Zelepuk @ Mar 31 2017, 10:52) *
Планируется разработка измерительного прибора .....

(1) Дело в том что нужно часто давать сигналы готовности данных на разных ступенях алгоритма. Использовать флаги - глобальные переменные неудобно (их будет слишком много).

(2) Сообщить, какие "более красивые подходы" для этого используются.
например на микрокотнтроллере можно использовать ОСРВ и ее средства взаимодействия между задачами,

(3) а как быть когда нужно сделать демо-проект на PC (для последующего переноса на МК)?

(4) Все это выглядит ужасно в бесконечном цикле.

(1) организуйте для глобальных данных одну структуру. Если не хотите уходить от "глобализации"
Работать со всеми глоб. данными можно через один указатель на нее.
(2) "красиво" можно сделать и без ОС. Зависит от сложности задачи и целесообразности использования ОС.
Многие ОС для МК имеют "порты" под PC/x86
(3) Проект для контроллера надо изначально писать с расчетом на "переносимость" -
на уровне компиляторов для MK и PC. В PC прокт компилировать-запускать в своем "эмуляторе".
(например вывод на SPI заменить на вывод в файл или консоль)
(4) Если "главный цикл" в основе Вас устраиевает - посмотрите на
оболочку protothread Dunkless. ОНО работает-компилируется и на MK, и на PC (проверено).
По-сути это оболочка для цикла.
Make_Pic
Цитата(bve @ Apr 6 2017, 21:22) *
Из Вашего обработчика вызовите свободное прерывание с нужным приоритетом.

Вопрос об использовании setjmp/longjmp в контексте использования простой ос подобной или самой CooS, но вместо AVR для Cortex M3/4, например STM32F0.
MrYuran
Цитата(Zelepuk @ Mar 31 2017, 10:52) *
Все это выглядит ужасно в бесконечном цикле.

Подскажите, как сделать грамотно.

Не знаю, грамотно или нет, но все, что вы описали, а меня в главном цикле выглядит как
Код
ProcessADC(&adc);

где реализован конечный автомат, работающий с АЦП и привязанный к конкретной структуре с набором параметров.
Естественно, никаких заднржек, ожиданий и тд. - атомарное действие и возврат

глобально объявляется структура adc (или несколько, если многоканальная система), а буфера и прочую требуху можно (нужно) вынести в отдельный модуль и объявить static, чтобы не лазить туда грязными ручками (и ножками)

буфера тоже в виде структур с необходимыми параметрами (включая указатели на обработчики). и вообще все это плавно приводит к необходимости перехода на с++, т.к.там это все реализуется естественным образом без ручных костылей.

а мэйн будет выглядеть так:
Код
Init();
while(1){
  ClearWDT();
  ProcessADC(&adc);
  ProcessData(&data);
  Poll(&interface);
  ProcessComand(&interface);
}

можно, конечно, сделать из батона троллейбус примотать сюда РТОС, но зачем?
TigerSHARC
Цитата(MrYuran @ Apr 8 2017, 08:06) *
Не знаю, грамотно или нет, но все, что вы описали, а меня в главном цикле выглядит как
Код
ProcessADC(&adc);


а мэйн будет выглядеть так:
Код
Init();
while(1){
  ClearWDT();
  ProcessADC(&adc);
  ProcessData(&data);
  Poll(&interface);
  ProcessComand(&interface);
}

можно, конечно, сделать из батона троллейбус примотать сюда РТОС, но зачем?

тогда вы должны быть уверены, что время выполнения
Poll(&interface);
и
ProcessComand(&interface);
детерминировано. Иначе возможны пропуски данных от ацп.

Цитата(MrYuran @ Apr 8 2017, 08:06) *
можно, конечно, сделать из батона троллейбус примотать сюда РТОС, но зачем?

РТОС нужна для выставления приоритета задач. У вас бы ProcessADC(&adc) имел наивысший приоритет. Наверное, с РТОС проще работать, если задач становится с десяток или больше... rolleyes.gif
MrYuran
Цитата(TigerSHARC @ Apr 8 2017, 11:16) *
Наверное, с РТОС проще работать, если задач становится с десяток или больше... rolleyes.gif

Скорее, если над проектом работает десяток взаимозаменяемых студентов и нет времени каждому объяснять, что почем.
Каждый пишет свой линейный кусочек, как учили в школе.

Как удачно однажды кто-то брякнул, снижается порок вхождения sm.gif
TigerSHARC
Цитата(MrYuran @ Apr 8 2017, 12:18) *
Скорее, если над проектом работает десяток взаимозаменяемых студентов и нет времени каждому объяснять, что почем.
Каждый пишет свой линейный кусочек, как учили в школе.

Как удачно однажды кто-то брякнул, снижается порок вхождения sm.gif

Далеко не только студенты пишут с использованием ртос. С ртос программу гараздо проще модифицировать. Хотя конечно если человек работает и хочет быть уверен что его не уволят так как исходный код прошивок может читать только он - тогда наверное лучше не использовать ртос.

Здесь в начале темы кто-то ссылку давал на статью хабра. Там хорошо описано требование использовать ртос.
Я видел программы где нужно было синхронизировать до 100 различных событий. Это все надо как- то синхронизировать. Зачем изобретать свой велосипед? Программа была написана на dsp/bios.
jcxz
Цитата(MrYuran @ Apr 8 2017, 11:18) *
Скорее, если над проектом работает десяток взаимозаменяемых студентов и нет времени каждому объяснять, что почем.
Каждый пишет свой линейный кусочек, как учили в школе.

Ну-ну...
Очевидно, что вы пишете только простые программы.
Представьте, что в вашей ProcessData() возможны моменты времени, когда требуется ей потратить много тактов CPU (например - прогнать данные через тяжёлый фильтр), а в ProcessADC() - необходима быстрая реакция на какие-то события (и нельзя вынести в ISR). Что будете делать в вашем суперцикле?
Другой случай:
Требуется энергосбережение и программа большую часть времени спит, просыпаясь только для обработки событий. Событий много, события составляют последовательность событий (событие1, за ним сбытие2, событие3, и т.п - это всё цепочка последовательных событий для одной задачи; у других задач - свои цепочки событий). Как будете обрабатывать их вашим суперциклом? При любом событии будете проходить весь цикл, все автоматы состояний для каждой из цепочек? В случае РТОС будет разбужена только одна задача, которая отвечает за обработку данного события (одной цепочки), которая восстановит контекст в точку обработки событияN цепочки M, обработает его, контекст сохранится в новой точке программы и CPU опять уйдёт в сон.

Суперцикл годен только для сравнительно простых программ. Скорее программок.
Программиста, пытающегося писать большие и сложные программные комплексы реального времени, с асинхронной реакцией на много разноприоритетных событий, да ещё когда условия задачи периодически меняются и дополняются, лучше сразу уволить.
Иначе, когда вдруг потребуется добавить в устройство совсем небольшой новый функционал обработки какой-то периферии например и окажется вдруг, что нужно весь этот суперцикл переписать. biggrin.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.