De nuevo sobre las plantillas C ++ en microcontroladores.

Introducción

La idea de usar plantillas C ++ para programar controladores no es nada nuevo; hay mucho material disponible en la web. Permítanme recordar brevemente las principales ventajas: transferir una parte significativa de los errores del tiempo de ejecución al tiempo de compilación debido a un estricto control de tipos, así como una aproximación a un enfoque orientado a objetos, que es cercano y conveniente para muchos, sin la necesidad de almacenar campos en una clase estática (todos los campos son parámetros de plantilla). Sin embargo, vale la pena señalar que casi todos los autores en general se limitan en sus trabajos a ejemplos de trabajo con registros y puertos de E / S. En mi artículo, quiero continuar con estas ideas.





No puedes estar un poco embarazada

La programación orientada a objetos implica la presencia de clases en un programa que interactúan entre sí. La interacción se expresa por la dependencia de unas clases de otras. Y aquí aparece la esencia del encabezado: para pasar una plantilla de clase B con métodos estáticos a la clase A como parámetro , entonces la clase B también debe hacerse plantilla, y así sucesivamente a lo largo de toda la cadena.





Por ejemplo, USART al menos depende de sus registros, entonces la declaración de la clase correspondiente se verá así (el código asociado con la declaración de registros se toma de aquí para garantizar la coherencia de los artículos, gracias @lamerok por los materiales geniales y ejemplos. No les he pasado envoltorios, pero planeo hacerlo):





template <typename _Regs>
class Usart
{
public:
  static void Init()
  {
    _Regs::CR1Pack<_Regs::CR1::UE, _Regs::CR1::RE, _Regs::CR1::TE>::Set();
    //  - .
  }
}
      
      



Descubrimos los registros para declarar una instancia de UART específica, necesita especializar la plantilla





using Usart1 = Usart<USART1>;
      
      



Todo parece estar bien, pero de hecho, una interfaz USART específica tiene diferentes dependencias:





  1. Registro de reloj (RCC_APB2).





  2. Número de interrupción.





  3. Un conjunto de posibles pines (Tx y Rx).





  4. Dma (Tx y Rx).





- - , . ,





template <typename _Regs, typename _ClockCtrl>
class Usart
{
public:
  static void Init()
  {
    //       
    _ClockCtrl::Enable()
    _Regs::CR1Pack<_Regs::CR1::UE, _Regs::CR1::RE, _Regs::CR1::TE>::Set();
    ...
  }
}
      
      



. , Init / RCC_ARB2, ?





-, , . , USART






//   TX UART  SPL.
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;
GPIO_Init(GPIOD, &GPIO_InitStructure); //

      
      



: , , , , . :





//   Tx  Rx .
template<typename _Regs, IRQn_Type _IRQNumber, typename _ClockCtrl, typename _TxPins, typename _RxPins, typename _DmaTx, typename _DmaRx>
template<typename TxPin, typename RxPin>
void Usart<_Regs, _IRQNumber, _ClockCtrl, _TxPins, _RxPins, _DmaTx, _DmaRx>::SelectTxRxPins()
{
  const int8_t txPinIndex = TypeIndex<TxPin, _TxPins>::value;
  const int8_t rxPinIndex = !std::is_same_v<RxPin, IO::NullPin>
        ? TypeIndex<RxPin, typename _RxPins>::value
        : -1; //    ,    NullPin   
  static_assert(txPinIndex >= 0);
  //    Rx 
  static_assert(rxPinIndex >= -1);
  SelectTxRxPins<txPinIndex, rxPinIndex>();
}
      
      



USART SelectTxRxPins , , - static_assert.





, , C++ GPIO, , .





//     DS1307
template <typename _I2CBus>
class Ds1307
{
  ...
  static Time GetDateTime()
  {
    Time time;
    _I2CBus::Read(Ds1307Address, 0x00, &time, sizeof(time));
    ...
      
      



, , :





using Rtc = Ds1307<I2c1>;
      
      



, , ( neiver, - ++ easyelectronics.ru) "". github "Mcucpp", . , , , , , ( , 2019, ). , , , , , Doxy-, , . Zhele, Stm32. , , , .





" , " © ..





, , gpio, , i2c/spi/uart/one-wire, , .





, . custom- CubeIDE. , , , , , , , , , , . .





  1. - ++





  2. Pin. ++ ( CortexM)





  3. ++ ( CortexM)





  4. AVR
















All Articles