Перейти к содержанию
    

Критерии совершенства в CubeMX?

18 minutes ago, Nixon said:

Да стартап у нас и описан на C++. 

Вот вам для примера для EFM32LG. Сделать его для любого другого семейства - час делов.

startup_efm32lg.cpp

startup_efm32lg.hpp

Особо порадовала эта строчка :biggrin:

using namespace nixon::system;

 

 

Я пошел немного по другому пути и немного дальше: все это "хозяйство" спрятал внутри класса Interrupt (шаблона точнее).

 

Vectors.hpp:

	class Interrupt final
	{
	public:
		using Index = int8_t;
		using Priority = uint8_t;
		using Vector = Delegate<void(void)>;
	
		Interrupt();

		void initialize(Index);
		void installVector(Vector&);
		void setPriority(Priority priority);
		void clearPending();

		void enable();
		void disable();
			
#ifdef DEBUG
		Property<char *> name;
#endif

	private:
		Index index;
	};
         

Реализация - в том же файле, где и таблица делегатов (у меня Vectors.cpp), она простейшая - используются наборы готовых макросов NVIC_xxx.

В этом случае достаточно лишь заинклудить Vectors.hpp в свой cpp-исходник и можем уже создавать свои прерывания и перенастраивать их на любой void() метод любого класса,

вся "срамота" скрыта внутри Vectors.cpp, таблица делегатов благодаря static никому больше не доступна. Победа!

 

После всего этого никаких startup файлов к проекту подключать больше не нужно, они просто не нужны :) Хотя цель была конечно же не в этом.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

17 минут назад, Forger сказал:

Я пошел немного по другому пути и немного дальше: все это "хозяйство" спрятал внутри класса Interrupt (шаблона точнее).

У меня была мысль сделать так же, но перевесило желание сделать все же модульную конструкцию, где контроллер прерываний и работа с ним это отдельная епархия

 

18 минут назад, Forger сказал:

Особо порадовала эта строчка :biggrin:

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

42 minutes ago, haker_fox said:

Кстати, а код этот читаемый? Если не секретный, можете дать хотя бы фрагмент для общего обозрения?

Да не проблема. Но инициализацию таблицы векторов показывать не буду, эт как ба не солидно для опытных разработчиков. 
 Скажем программа вот для такой диаграммы (хотя это не SateFlow, но суть не меняется). Эт начало  приложения типа  sensor fusion

image.thumb.png.e4cf211ef7d8655fd683cae54ca1b70c.png

Тут на одном скриншоте показаны основная диаграмма и ниже два ее субблока.
А вот текст программы:

 

Spoiler

/*
 * freedomk64f_I2C_tempSensor.c
 *
 * Code generation for model "freedomk64f_I2C_tempSensor".
 *
 * Model version              : 1.142
 * Simulink Coder version : 9.0 (R2018b) 24-May-2018
 * C source code generated on : Mon Jan 14 17:06:53 2019
 *
 * Target selection: ert.tlc
 * Note: GRT includes extra infrastructure and instrumentation for prototyping
 * Embedded hardware selection: ARM Compatible->ARM Cortex
 * Code generation objectives: Unspecified
 * Validation result: Not run
 */

#include "freedomk64f_I2C_tempSensor.h"
#include "freedomk64f_I2C_tempSensor_private.h"

/* Block states (default storage) */
DW_freedomk64f_I2C_tempSensor_T freedomk64f_I2C_tempSensor_DW;

/* Real-time model */
RT_MODEL_freedomk64f_I2C_temp_T freedomk64f_I2C_tempSensor_M_;
RT_MODEL_freedomk64f_I2C_temp_T *const freedomk64f_I2C_tempSensor_M =
  &freedomk64f_I2C_tempSensor_M_;

/* Forward declaration for local functions */
static void freedomk6_SystemCore_release_lb(const
  freedomk64f_I2CMasterWrite_fr_T *obj);
static void freedomk64_SystemCore_delete_he(const
  freedomk64f_I2CMasterWrite_fr_T *obj);
static void matlabCodegenHandle_matlabCo_do(freedomk64f_I2CMasterWrite_fr_T *obj);
static void freedomk64f__SystemCore_release(const
  freedomk64f_I2CMasterRead_fre_T *obj);
static void freedomk64f_I_SystemCore_delete(const
  freedomk64f_I2CMasterRead_fre_T *obj);
static void matlabCodegenHandle_matlabCodeg(freedomk64f_I2CMasterRead_fre_T *obj);

/* Forward declaration for local functions */
static void freedomk6_SystemCore_release_dt(const
  freedomk64f_I2CMasterRead_fre_T *obj);
static void freedomk64_SystemCore_delete_dt(const
  freedomk64f_I2CMasterRead_fre_T *obj);
static void matlabCodegenHandle_matlabC_dtd(freedomk64f_I2CMasterRead_fre_T *obj);
static void freedomk64_SystemCore_release_d(const
  freedomk64f_DigitalWrite_free_T *obj);
static void freedomk64f_SystemCore_delete_d(const
  freedomk64f_DigitalWrite_free_T *obj);
static void matlabCodegenHandle_matlabCo_dt(freedomk64f_DigitalWrite_free_T *obj);
static void freedomk6_SystemCore_release_lb(const
  freedomk64f_I2CMasterWrite_fr_T *obj)
{
  if ((obj->isInitialized == 1) && obj->isSetupComplete) {
    MW_I2C_Close(obj->MW_I2C_HANDLE);
  }
}

static void freedomk64_SystemCore_delete_he(const
  freedomk64f_I2CMasterWrite_fr_T *obj)
{
  freedomk6_SystemCore_release_lb(obj);
}

static void matlabCodegenHandle_matlabCo_do(freedomk64f_I2CMasterWrite_fr_T *obj)
{
  if (!obj->matlabCodegenIsDeleted) {
    obj->matlabCodegenIsDeleted = true;
    freedomk64_SystemCore_delete_he(obj);
  }
}

static void freedomk64f__SystemCore_release(const
  freedomk64f_I2CMasterRead_fre_T *obj)
{
  if ((obj->isInitialized == 1) && obj->isSetupComplete) {
    MW_I2C_Close(obj->MW_I2C_HANDLE);
  }
}

static void freedomk64f_I_SystemCore_delete(const
  freedomk64f_I2CMasterRead_fre_T *obj)
{
  freedomk64f__SystemCore_release(obj);
}

static void matlabCodegenHandle_matlabCodeg(freedomk64f_I2CMasterRead_fre_T *obj)
{
  if (!obj->matlabCodegenIsDeleted) {
    obj->matlabCodegenIsDeleted = true;
    freedomk64f_I_SystemCore_delete(obj);
  }
}

/* Start for enable system: '<Root>/One_time_initialization' */
void f_One_time_initialization_Start(DW_One_time_initialization_fr_T *localDW,
  P_One_time_initialization_fre_T *localP)
{
  freedomk64f_I2CMasterWrite_fr_T *obj;
  uint32_T i2cname;
  freedomk64f_I2CMasterRead_fre_T *obj_0;

  /* Start for MATLABSystem: '<S2>/I2C Master Write1' */
  localDW->obj_e.matlabCodegenIsDeleted = true;
  localDW->obj_e.isInitialized = 0;
  localDW->obj_e.matlabCodegenIsDeleted = false;
  localDW->objisempty = true;

  /* [EOF] */
  /*  */
  obj = &localDW->obj_e;
  localDW->obj_e.isSetupComplete = false;
  localDW->obj_e.isInitialized = 1;
  i2cname = 0;
  obj->MW_I2C_HANDLE = MW_I2C_Open(i2cname, 0);

  /* 100KHz. */
  /* KHz */
  localDW->obj_e.BusSpeed = 100000U;
  MW_I2C_SetBusSpeed(localDW->obj_e.MW_I2C_HANDLE, localDW->obj_e.BusSpeed);
  localDW->obj_e.isSetupComplete = true;

  /* Start for MATLABSystem: '<S2>/I2C Master Write2' */
  localDW->obj_o.matlabCodegenIsDeleted = true;
  localDW->obj_o.isInitialized = 0;
  localDW->obj_o.matlabCodegenIsDeleted = false;
  localDW->objisempty_o = true;

  /* [EOF] */
  /*  */
  obj = &localDW->obj_o;
  localDW->obj_o.isSetupComplete = false;
  localDW->obj_o.isInitialized = 1;
  i2cname = 0;
  obj->MW_I2C_HANDLE = MW_I2C_Open(i2cname, 0);

  /* 100KHz. */
  /* KHz */
  localDW->obj_o.BusSpeed = 100000U;
  MW_I2C_SetBusSpeed(localDW->obj_o.MW_I2C_HANDLE, localDW->obj_o.BusSpeed);
  localDW->obj_o.isSetupComplete = true;

  /* Start for MATLABSystem: '<S2>/I2C Master Read1' */
  localDW->obj.matlabCodegenIsDeleted = true;
  localDW->obj.isInitialized = 0;
  localDW->obj.matlabCodegenIsDeleted = false;
  localDW->objisempty_k = true;

  /* [EOF] */
  /*  */
  localDW->obj.SampleTime = localP->I2CMasterRead1_SampleTime;
  obj_0 = &localDW->obj;
  localDW->obj.isSetupComplete = false;
  localDW->obj.isInitialized = 1;
  i2cname = 0;
  obj_0->MW_I2C_HANDLE = MW_I2C_Open(i2cname, 0);

  /* 100KHz. */
  /* KHz */
  localDW->obj.BusSpeed = 100000U;
  MW_I2C_SetBusSpeed(localDW->obj.MW_I2C_HANDLE, localDW->obj.BusSpeed);
  localDW->obj.isSetupComplete = true;

  /* Start for MATLABSystem: '<S2>/I2C Master Read2' */
  localDW->obj_b.matlabCodegenIsDeleted = true;
  localDW->obj_b.isInitialized = 0;
  localDW->obj_b.matlabCodegenIsDeleted = false;
  localDW->objisempty_d = true;

  /* [EOF] */
  /*  */
  localDW->obj_b.SampleTime = localP->I2CMasterRead2_SampleTime;
  obj_0 = &localDW->obj_b;
  localDW->obj_b.isSetupComplete = false;
  localDW->obj_b.isInitialized = 1;
  i2cname = 0;
  obj_0->MW_I2C_HANDLE = MW_I2C_Open(i2cname, 0);

  /* 100KHz. */
  /* KHz */
  localDW->obj_b.BusSpeed = 100000U;
  MW_I2C_SetBusSpeed(localDW->obj_b.MW_I2C_HANDLE, localDW->obj_b.BusSpeed);
  localDW->obj_b.isSetupComplete = true;
}

/* Output and update for enable system: '<Root>/One_time_initialization' */
void freedom_One_time_initialization(boolean_T rtu_Enable,
  DW_One_time_initialization_fr_T *localDW, P_One_time_initialization_fre_T
  *localP)
{
  uint8_T b_SwappedDataBytes[2];
  uint8_T b_output;
  uint8_T status;

  /* Outputs for Enabled SubSystem: '<Root>/One_time_initialization' incorporates:
   *  EnablePort: '<S2>/Enable'
   */
  if (rtu_Enable) {
    /* MATLABSystem: '<S2>/I2C Master Write1' incorporates:
     *  Constant: '<S2>/Constant1'
     */
    b_SwappedDataBytes[0] = 91U;
    b_SwappedDataBytes[1] = localP->Constant1_Value;
    MW_I2C_MasterWrite(localDW->obj_e.MW_I2C_HANDLE, 29U, b_SwappedDataBytes, 2U,
                       false, false);

    /* MATLABSystem: '<S2>/I2C Master Write2' incorporates:
     *  Constant: '<S2>/Constant2'
     */
    b_SwappedDataBytes[0] = 42U;
    b_SwappedDataBytes[1] = localP->Constant2_Value;
    MW_I2C_MasterWrite(localDW->obj_o.MW_I2C_HANDLE, 29U, b_SwappedDataBytes, 2U,
                       false, false);

    /* MATLABSystem: '<S2>/I2C Master Read1' */
    if (localDW->obj.SampleTime != localP->I2CMasterRead1_SampleTime) {
      localDW->obj.SampleTime = localP->I2CMasterRead1_SampleTime;
    }

    status = 91U;
    status = MW_I2C_MasterWrite(localDW->obj.MW_I2C_HANDLE, 29U, &status, 1U,
      true, false);
    if (0 == status) {
      MW_I2C_MasterRead(localDW->obj.MW_I2C_HANDLE, 29U, &status, 1U, false,
                        true);
      memcpy((void *)&b_output, (void *)&status, (uint32_T)((size_t)1 * sizeof
              (uint8_T)));
    }

    /* End of MATLABSystem: '<S2>/I2C Master Read1' */

    /* MATLABSystem: '<S2>/I2C Master Read2' */
    if (localDW->obj_b.SampleTime != localP->I2CMasterRead2_SampleTime) {
      localDW->obj_b.SampleTime = localP->I2CMasterRead2_SampleTime;
    }

    status = 42U;
    status = MW_I2C_MasterWrite(localDW->obj_b.MW_I2C_HANDLE, 29U, &status, 1U,
      true, false);
    if (0 == status) {
      MW_I2C_MasterRead(localDW->obj_b.MW_I2C_HANDLE, 29U, &status, 1U, false,
                        true);
      memcpy((void *)&b_output, (void *)&status, (uint32_T)((size_t)1 * sizeof
              (uint8_T)));
    }

    /* End of MATLABSystem: '<S2>/I2C Master Read2' */
  }

  /* End of Outputs for SubSystem: '<Root>/One_time_initialization' */
}

/* Termination for enable system: '<Root>/One_time_initialization' */
void fr_One_time_initialization_Term(DW_One_time_initialization_fr_T *localDW)
{
  /* Terminate for MATLABSystem: '<S2>/I2C Master Write1' */
  matlabCodegenHandle_matlabCo_do(&localDW->obj_e);

  /* Terminate for MATLABSystem: '<S2>/I2C Master Write2' */
  matlabCodegenHandle_matlabCo_do(&localDW->obj_o);

  /* Terminate for MATLABSystem: '<S2>/I2C Master Read1' */
  matlabCodegenHandle_matlabCodeg(&localDW->obj);

  /* Terminate for MATLABSystem: '<S2>/I2C Master Read2' */
  matlabCodegenHandle_matlabCodeg(&localDW->obj_b);
}

static void freedomk6_SystemCore_release_dt(const
  freedomk64f_I2CMasterRead_fre_T *obj)
{
  if ((obj->isInitialized == 1) && obj->isSetupComplete) {
    MW_I2C_Close(obj->MW_I2C_HANDLE);
  }
}

static void freedomk64_SystemCore_delete_dt(const
  freedomk64f_I2CMasterRead_fre_T *obj)
{
  freedomk6_SystemCore_release_dt(obj);
}

static void matlabCodegenHandle_matlabC_dtd(freedomk64f_I2CMasterRead_fre_T *obj)
{
  if (!obj->matlabCodegenIsDeleted) {
    obj->matlabCodegenIsDeleted = true;
    freedomk64_SystemCore_delete_dt(obj);
  }
}

static void freedomk64_SystemCore_release_d(const
  freedomk64f_DigitalWrite_free_T *obj)
{
  if ((obj->isInitialized == 1) && obj->isSetupComplete) {
    MW_digitalIO_close(obj->MW_DIGITALIO_HANDLE);
  }
}

static void freedomk64f_SystemCore_delete_d(const
  freedomk64f_DigitalWrite_free_T *obj)
{
  freedomk64_SystemCore_release_d(obj);
}

static void matlabCodegenHandle_matlabCo_dt(freedomk64f_DigitalWrite_free_T *obj)
{
  if (!obj->matlabCodegenIsDeleted) {
    obj->matlabCodegenIsDeleted = true;
    freedomk64f_SystemCore_delete_d(obj);
  }
}

/* Model step function */
void freedomk64f_I2C_tempSensor_step(void)
{
  /* local block i/o variables */
  boolean_T rtb_HiddenBuf_InsertedFor_One_t;
  int8_T output;
  uint8_T status;

  /* Outputs for Enabled SubSystem: '<Root>/Execution_loop' incorporates:
   *  EnablePort: '<S1>/Enable'
   */
  /* UnitDelay: '<Root>/Unit Delay' */
  if (freedomk64f_I2C_tempSensor_DW.UnitDelay_DSTATE) {
    /* MATLABSystem: '<S1>/I2C Master Read' */
    if (freedomk64f_I2C_tempSensor_DW.obj.SampleTime !=
        freedomk64f_I2C_tempSensor_P.I2CMasterRead_SampleTime) {
      freedomk64f_I2C_tempSensor_DW.obj.SampleTime =
        freedomk64f_I2C_tempSensor_P.I2CMasterRead_SampleTime;
    }

    status = 81U;
    status = MW_I2C_MasterWrite(freedomk64f_I2C_tempSensor_DW.obj.MW_I2C_HANDLE,
      29U, &status, 1U, true, false);
    if (0 == status) {
      MW_I2C_MasterRead(freedomk64f_I2C_tempSensor_DW.obj.MW_I2C_HANDLE, 29U,
                        &status, 1U, false, true);
      memcpy((void *)&output, (void *)&status, (uint32_T)((size_t)1 * sizeof
              (int8_T)));
    } else {
      output = 0;
    }

    /* Switch: '<S1>/Switch' incorporates:
     *  Constant: '<S1>/Constant'
     *  Constant: '<S1>/Constant1'
     *  Gain: '<S1>/Gain'
     *  MATLABSystem: '<S1>/I2C Master Read'
     */
    if ((real32_T)freedomk64f_I2C_tempSensor_P.Gain_Gain * 0.0078125F *
        (real32_T)output > freedomk64f_I2C_tempSensor_P.Switch_Threshold) {
      status = freedomk64f_I2C_tempSensor_P.Constant_Value_a;
    } else {
      status = freedomk64f_I2C_tempSensor_P.Constant1_Value;
    }

    /* End of Switch: '<S1>/Switch' */

    /* MATLABSystem: '<S1>/Digital Write' */
    MW_digitalIO_write(freedomk64f_I2C_tempSensor_DW.obj_m.MW_DIGITALIO_HANDLE,
                       status != 0);
  }

  /* End of Outputs for SubSystem: '<Root>/Execution_loop' */

  /* SignalConversion: '<Root>/HiddenBuf_InsertedFor_One_time_initialization_at_inport_0' incorporates:
   *  Logic: '<Root>/Logical Operator'
   *  UnitDelay: '<Root>/Unit Delay'
   */
  rtb_HiddenBuf_InsertedFor_One_t =
    !freedomk64f_I2C_tempSensor_DW.UnitDelay_DSTATE;

  /* Outputs for Enabled SubSystem: '<Root>/One_time_initialization' */
  freedom_One_time_initialization(rtb_HiddenBuf_InsertedFor_One_t,
    &freedomk64f_I2C_tempSensor_DW.One_time_initialization,
    &freedomk64f_I2C_tempSensor_P.One_time_initialization);

  /* End of Outputs for SubSystem: '<Root>/One_time_initialization' */

  /* Update for UnitDelay: '<Root>/Unit Delay' incorporates:
   *  Constant: '<Root>/Constant'
   */
  freedomk64f_I2C_tempSensor_DW.UnitDelay_DSTATE =
    freedomk64f_I2C_tempSensor_P.Constant_Value;
}

/* Model initialize function */
void freedomk64f_I2C_tempSensor_initialize(void)
{
  /* Registration code */

  /* initialize error status */
  rtmSetErrorStatus(freedomk64f_I2C_tempSensor_M, (NULL));

  /* states (dwork) */
  (void) memset((void *)&freedomk64f_I2C_tempSensor_DW, 0,
                sizeof(DW_freedomk64f_I2C_tempSensor_T));

  {
    freedomk64f_I2CMasterRead_fre_T *obj;
    uint32_T i2cname;
    freedomk64f_DigitalWrite_free_T *obj_0;

    /* Start for Enabled SubSystem: '<Root>/Execution_loop' */
    /* Start for MATLABSystem: '<S1>/I2C Master Read' */
    freedomk64f_I2C_tempSensor_DW.obj.matlabCodegenIsDeleted = true;
    freedomk64f_I2C_tempSensor_DW.obj.isInitialized = 0;
    freedomk64f_I2C_tempSensor_DW.obj.matlabCodegenIsDeleted = false;
    freedomk64f_I2C_tempSensor_DW.objisempty = true;

    /* [EOF] */
    /*  */
    freedomk64f_I2C_tempSensor_DW.obj.SampleTime =
      freedomk64f_I2C_tempSensor_P.I2CMasterRead_SampleTime;
    obj = &freedomk64f_I2C_tempSensor_DW.obj;
    freedomk64f_I2C_tempSensor_DW.obj.isSetupComplete = false;
    freedomk64f_I2C_tempSensor_DW.obj.isInitialized = 1;
    i2cname = 0;
    obj->MW_I2C_HANDLE = MW_I2C_Open(i2cname, 0);

    /* 100KHz. */
    /* KHz */
    freedomk64f_I2C_tempSensor_DW.obj.BusSpeed = 100000U;
    MW_I2C_SetBusSpeed(freedomk64f_I2C_tempSensor_DW.obj.MW_I2C_HANDLE,
                       freedomk64f_I2C_tempSensor_DW.obj.BusSpeed);
    freedomk64f_I2C_tempSensor_DW.obj.isSetupComplete = true;

    /* Start for MATLABSystem: '<S1>/Digital Write' */
    freedomk64f_I2C_tempSensor_DW.obj_m.matlabCodegenIsDeleted = true;
    freedomk64f_I2C_tempSensor_DW.obj_m.isInitialized = 0;
    freedomk64f_I2C_tempSensor_DW.obj_m.matlabCodegenIsDeleted = false;
    freedomk64f_I2C_tempSensor_DW.objisempty_k = true;

    /* [EOF] */
    obj_0 = &freedomk64f_I2C_tempSensor_DW.obj_m;
    freedomk64f_I2C_tempSensor_DW.obj_m.isSetupComplete = false;
    freedomk64f_I2C_tempSensor_DW.obj_m.isInitialized = 1;
    obj_0->MW_DIGITALIO_HANDLE = MW_digitalIO_open(42U, 1);
    freedomk64f_I2C_tempSensor_DW.obj_m.isSetupComplete = true;

    /* End of Start for SubSystem: '<Root>/Execution_loop' */

    /* Start for Enabled SubSystem: '<Root>/One_time_initialization' */
    f_One_time_initialization_Start
      (&freedomk64f_I2C_tempSensor_DW.One_time_initialization,
       &freedomk64f_I2C_tempSensor_P.One_time_initialization);

    /* End of Start for SubSystem: '<Root>/One_time_initialization' */
  }

  /* InitializeConditions for UnitDelay: '<Root>/Unit Delay' */
  freedomk64f_I2C_tempSensor_DW.UnitDelay_DSTATE =
    freedomk64f_I2C_tempSensor_P.UnitDelay_InitialCondition;
}

/* Model terminate function */
void freedomk64f_I2C_tempSensor_terminate(void)
{
  /* Terminate for Enabled SubSystem: '<Root>/Execution_loop' */
  /* Terminate for MATLABSystem: '<S1>/I2C Master Read' */
  matlabCodegenHandle_matlabC_dtd(&freedomk64f_I2C_tempSensor_DW.obj);

  /* Terminate for MATLABSystem: '<S1>/Digital Write' */
  matlabCodegenHandle_matlabCo_dt(&freedomk64f_I2C_tempSensor_DW.obj_m);

  /* End of Terminate for SubSystem: '<Root>/Execution_loop' */

  /* Terminate for Enabled SubSystem: '<Root>/One_time_initialization' */
  fr_One_time_initialization_Term
    (&freedomk64f_I2C_tempSensor_DW.One_time_initialization);

  /* End of Terminate for SubSystem: '<Root>/One_time_initialization' */
}

 

Текст большой, но его не читают. Нет причин. 
Отладка ведется в модели. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

9 minutes ago, Nixon said:

У меня была мысль сделать так же, но перевесило желание сделать все же модульную конструкцию, где контроллер прерываний и работа с ним это отдельная епархия

А мне как раз пришлось все запихнуть в один Vectors.cpp, хотя раньше было раздельно. Точную причину не помню, но вроде что-то связанное с компилятором clang v6 от ARM, точнее - с линкером.

После обновки это вроде исправили, но возвращать обратно смысла уже не вижу ))

 

Quote

 

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

Аналогично :)

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

4 minutes ago, AlexandrY said:

Текст большой, но его не читают. Нет причин. 
Отладка ведется в модели. 

Что самое интересное, MATLAB свои модели строит по умолчанию опираясь на СMSIS RTOS т.е. на RTX и использует стандартные SDK производителей, т.е. для STM32 это будут тексты сгенерированные Cube. Все, круг замкнулся. И все встало на свои места. 
Итог:   
Те кто пишет под STM32 должны использовать Cube чтобы иметь возможность использовать Simulink, а тот в свою очередь для StateFlow. 
И получит в результате многократное повышение продуктивности программирования. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

38 minutes ago, AlexandrY said:

Текст большой, но его не читают. Нет причин. 

Что-то в этом есть. Но уж слишком гладко всё получается. Ведь есть, же наверняка, какой-то подвох?

Ну например, ошибки (ерраты) в железе конечного микроконтроллера? Тогда возможны правки исходников. А это уже нарушение такой идеологии. 

Вы уже сделали с помощью этого инструмента реально продаваемые изделия?

30 minutes ago, AlexandrY said:

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

Тысячу раз "гм"... Смотря какие алгоритмы, ИМХО. Стек TCP/IP если свой захочется сделать, его вряд ли целесообразно строить на диаграммах.

Кстати! Портируемость у такого решения тоже под вопросом.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 часа назад, Nixon сказал:

Чтобы динамически при создании компонентов можно было использовать функции-члены классов как обработчики прерываний и используется вторая таблица, которая находится в ОЗУ.

Для использования членов классов как обработчиков достаточно "обертки" вроде 

extern "C" void ADC_IRQHandler(void)
{
    ADC_.handler();
}

Получается, смысл второй таблицы именно в том, чтобы отложить привязку функции-члена с этапа компиляции на этап исполнения? И это делается для того, чтобы делать глобальным не объект, обрабатывающий прерывание а общий для всех прерываний объект, т.е. таблицу?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

15 minutes ago, Сергей Борщ said:

И это делается для того, чтобы делать глобальным не объект, обрабатывающий прерывание а общий для всех прерываний объект, т.е. таблицу?

Это делается для того, чтобы как раз ничего не делать глобальным и доступным "из каждой щели".

Просто, глобальными объектами в свое время я наелся по самые уши и больше не хочу повторять ((

 

Вот пример, чтобы прояснить картину:

https://electronix.ru/forum/index.php?app=forums&amp;module=forums&amp;controller=topic&amp;id=150276&amp;do=findComment&amp;comment=1603824


 

Также отложенное (управляемое) подключение векторов нужно (мне нужно) для изоляции библиотеки периферии и кода.

В том примере это также показано (на примере аппаратного таймера TimerTIM2).

Т. е. сама периферия ничего не знает о конкретном векторе прерывания, "обслуживающем" ее.

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

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

В этом случае возможность отключения обработчика может оказаться полезной.

 

Да и вообще, при желании тот же таймер можно уничтожить, таком образом вызовется его деструктор,  где автоматом сбросится этот таймер и отключится его обработчик.

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

Конечно, это в некотором роде - сомнительная необходимость, но она есть и получилась просто так - бонусом. Изначально цели такой у меня не было.

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

42 минуты назад, Forger сказал:

Это делается для того, чтобы как раз ничего не делать глобальным и доступным "из каждой щели".

Просто, глобальными объектами в свое время я наелся по самые уши и больше не хочу повторять ((

Так что мешает при написании драйвера устройства (допустим, SPI), вынести его обработчик прерывания в этот же файл как interrupt-составляющую драйвера? Это, как по мне, куда нагляднее и сразу видно, какой драйвер какие прерывания использует. Ну работает обработчик с некими внешними переменными - в буфер символ записывает, допустим, нужен вот сам буфер, и пара глобальных флажков. Объявили это в файле-владельце, а extern в .h-ник...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

25 minutes ago, Arlleex said:

Так что мешает при написании драйвера устройства (допустим, SPI), вынести его обработчик прерывания в этот же файл как interrupt-составляющую драйвера?

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

Например, тот же семафор, который должен быть одновременно доступен и внутри задачи (у меня это экземпляры классов OS::Thread<>) и внутри обработчика.

Это вынуждает сам экземпляр семафора выносить за пределы объявления задачи либо выносить его в секцию public задачи, что уже вынуждает делать видимой в обработчике экземпляр этой задачи...

Короче, "куда не кинь всюду клин".

 

Quote

 

Это, как по мне, куда нагляднее и сразу видно, какой драйвера какие прерывания использует. Ну работает обработчик с некими внешними переменными - в буфер символ записывает, допустим, нужен вот сам буфер, и пара глобальных флажков. Объявили это в файле-владельце, а extern в .h-ник...

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

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

 

Короче, сложного не читаемого кода стало настолько много, что я в конце концов сделал все именно так, как мне нужно.

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

Короче, решена:

1) проблема видимости объектов

2) исключена необходимость делать объекты глобальными или на край давать им static приписку, что по сути - костыль.

3) да и вообще, вполне логично чтобы обработчики прерываний были полноценными методами любого класса, причем размещенные в секции private, да кто ж в своем уме от такого откажется :dirol:

 

Разумеется, к анахронизму - статические C-функции обработчики прерываний, груда глобальных флажков и всякого подобного мусора ... Больше к этому не вернусь. Нафик. Нужно двигаться дальше, а не топтаться на месте :)

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для этого вам нужно как минимум знать какой вектор используется и т.д.

Я приведу другой пример. Микроконтроллер, 6 уартов. Шаблонный класс уарта, который в зависимости от параметров шаблона при создании экземпляра класса сам автоматически подключит в качестве обработчика прерывания по приему/передаче функцию данного класса, которая осуществляет прием, буферизацию, разбор пакетов и т.д.

2 @Forger - ответили одновременно

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, Forger сказал:

Это делается для того, чтобы как раз ничего не делать глобальным и доступным "из каждой щели".

Но vectorTable же должна быть видна, иначе как в нее объекты указатели на свои функции-члены прописывать будут? Ваш шаблон-делегат вкурить не смог, каюсь. Видать, не дорос еще. Как вы массив размера IRQ_VECTOR_TABLE_SIZE заполняете одним DELEGATE() тоже не осилил.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

16 minutes ago, Сергей Борщ said:

Но vectorTable же должна быть видна, иначе как в нее объекты указатели на свои функции-члены прописывать будут?

Нет, не должна быть. Все происходит через класс Interrupt, реализация которого находится в том же файле, что и таблица делегатов всех обработчиков - Vectors.cpp.

Т.е. нужно лишь создать экземпляр Interrupt, см. выше, я приводил его содержимое.

Но эти Interrupt создаются автоматом внутри библиотеки соотв. периферии. Там же включаются/выключаются, а уже сама периферия представляет способ подключить нужный делегат - обработчик прерывания.

Например, в библиотеке CAN шины аж четыре (!) экземпляра Interrupt, и для каждого из них можно подключить свой обработчик.  На каждый обработчик еще куча флажков самого CAN ...

И такая картина для каждого экземпляра CAN. Короче, если все это добро упрятать в отлаженную библиотеку, то пользоваться будет одно удовольствие. Что я и сделал ))

 

 

Quote

Как вы массив размера IRQ_VECTOR_TABLE_SIZE заполняете одним DELEGATE() тоже не осилил.

Заполняются они дальше в соотв. цикле,  а тут это лишь для наглядности, чтобы было понятно, чем именно заполняются ))

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

6 часов назад, Forger сказал:

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

Причём тут "глобальные флажки"? Глобальными объектами нужно делать только те, которые нужны разным файлам. Если (как указывалось) пишется драйвер чего-либо, и этот драйвер в себя включает  ISR + набор переменных/констант + задачу ОС, то никаких проблем нет разместить всё это в отдельном файле. Без всяких "глобальных флажков". А глобальными сделать только конкретные функции/переменные API этого драйвера. И только их описание вынести в .h.

Именно так всегда и стараюсь делать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

13 часов назад, haker_fox сказал:

делать стартапы не на ассемблере, классически, а описывать прямов в *.cpp файлах

Универсальный стартап. Всего несколько строк на С. Всё очень гибко. Таблицы обработчиков отделены от собственно кода стартапа и легко добавляются (генерируются скриптом), на данный момент их там уже, наверное, за сотню.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...