Jump to content

    

Организация программ

Zelepuk, а не хотите попробовать Matlab/Simulink/Embedded Coder под это дело? Ваша задача выглядит типовой для этого.

Т.е. всю обработку данных и свои алгоритмы нарисовать в Simulink в виде модели, которую вы сможете моделировать на PC вместе с входными данными, а затем всю модель выгрузить за несколько кликов в Си код, который будет исполняться в реальном времени на вашем контроллере. И все это без морок с глобальными флагами и переменными и часто даже без ОСРВ. Это достаточно "красивый" подход с заделом на будущее. Называется Model-Based Design.

Share this post


Link to post
Share on other sites
Проще тогда наверное Keil с его ОС использовать. Хоть только за Keil платить придется...

Да, Keil - это благо. И ОС там легкая.

Share this post


Link to post
Share on other sites
Zelepuk, а не хотите попробовать Matlab/Simulink/Embedded Coder под это дело? Ваша задача выглядит типовой для этого.

Т.е. всю обработку данных и свои алгоритмы нарисовать в Simulink в виде модели, которую вы сможете моделировать на PC вместе с входными данными, а затем всю модель выгрузить за несколько кликов в Си код, который будет исполняться в реальном времени на вашем контроллере. И все это без морок с глобальными флагами и переменными и часто даже без ОСРВ. Это достаточно "красивый" подход с заделом на будущее. Называется Model-Based Design.

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

Share this post


Link to post
Share on other sites
Генерируемый код весьма труден для понимания.

Его не надо читать и понимать. Достаточно знать, что он делает то же самое, что и в симуляции.

принять байт от SPI, накопить буфер, посчитать среднее раз в 100мс.

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

Share this post


Link to post
Share on other sites
Почем-то мне думается что там не все так просто и красиво как описывается. посмотреть бы пример реализации такого подхода. Генерируемый код весьма труден для понимания. Увидеть бы готовый вариант простой процедуры: принять байт от SPI, накопить буфер, посчитать среднее раз в 100мс.

Что там трудного?:

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. Для других ОС примерно так же.

Share this post


Link to post
Share on other sites
Его не надо читать и понимать. Достаточно знать, что он делает то же самое, что и в симуляции.

 

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

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

 

 

Share this post


Link to post
Share on other sites
Бесплатная то она бесплатная, но мне только через 2 месяца пришел ответ типа извините мы были перегружены запросами, хотим продолжить общение.

И на очередной запрос опять зависли.

Посмотрите сами, она бесплатна только для некоммерческого применения за все остальное надо платить. https://www.micrium.com/buy/licensing/

Share this post


Link to post
Share on other sites
Т.е. всю обработку данных и свои алгоритмы нарисовать в Simulink в виде модели, которую вы сможете моделировать на PC вместе с входными данными, а затем всю модель выгрузить за несколько кликов в Си код, который будет исполняться в реальном времени на вашем контроллере.

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

Или вы реальным временем обзываете все что только способно выполняться в микроконтроллере? :biggrin:

 

Посмотрите сами, она бесплатна только для некоммерческого применения за все остальное надо платить. https://www.micrium.com/buy/licensing/

Ну если вам так хочется делать бизнес и никому не платить, что поделаешь? Проходите мимо. :laughing:

Share this post


Link to post
Share on other sites
Ну если вам так хочется делать бизнес и никому не платить, что поделаешь? Проходите мимо. :laughing:

Вы сами то поняли на что ответили? Я ее как раз и не стал использовать, только потому, что она очень дорого выходит для штучных коммерческих изделий.

Share this post


Link to post
Share on other sites
примерно 50кБ.

Если считать, что принять байт от SPI, накопить буфер, - это делает Ваш драйвер SPI, а сама процедура посчитать среднее вызывается раз в 100мс, и ей передается массив из 50000 значений, то в Симулинке она будет выглядеть так:

post-25368-1490987723_thumb.png

Рассчитано для исходного типа int8, результата суммы int32.

Тогда сгенерированный код будет выглядеть вот так:

ert_main.c - функция main

/*
/*
* 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 - собственно сам расчет среднего

/*
* 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 вдруг гарантирует нам выполнение в реальном времени?

Посмотрите первый комментарий в первом из сгенерированных файлов.

Share this post


Link to post
Share on other sites
Посмотрите первый комментарий в первом из сгенерированных файлов.

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

Они над вами смеются. Заметили скобочки?

Прочитайте весь комментарий.

Они оставляют за собой право сделать "Overrun" и посылают вас самих это расхлебывать.

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

Так что не надо нам этих фэйков. :biggrin:

Я ее как раз и не стал использовать, только потому, что она очень дорого выходит для штучных коммерческих изделий.

Не знаю, я делаю штучные и коммерческие, я мэйкер. Мне бесплатно.

Share this post


Link to post
Share on other sites
Они оставляют за собой право сделать "Overrun" и посылают вас самих это расхлебывать.

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

 

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

А в чем проблема?

rt_OneStep в примере предлагается вызывать в прерывании от таймера.

Во время исполнения модельного кода флаг Overrun ставится в true, а после завершения сбрасывается. Если следующее прерывание от таймера произойдет до окончания исполнения модельного кода, факт overrun ловится и делай, сам, что считаешь нужным.

Вообще-то ert_main.c - это всего лишь пример, как можно запустить функцию на исполнение в реальном времени без ОСРВ. Его можно без проблем изменять по своему усмотрению.

Share this post


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

Никак, в Simulink вы её не расхлебаете и даже не узнаете о ней.

Симулинк будет тупо раз за разом перезаписывать свои заглушки поверх ваших правок.

Его код предназначен для устойчивой среды исполнения на базе RTOS уже сделанной в микроконтроллере.

 

Вы же так и делаете. Используете vxWorks, а тут подсовываете надуманную лабуду.

Share this post


Link to post
Share on other sites
Симулинк будет тупо раз за разом перезаписывать свои заглушки поверх ваших правок.

Не понимаю я вас. Где и что Симулинк будет перезаписывать?

Share this post


Link to post
Share on other sites
Не знаю, я делаю штучные и коммерческие, я мэйкер. Мне бесплатно.

Это ваше оправдание, можете жить спокойно, только не заглядывайте на страничку о покупке microc os и не читайте про лицензии.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now