Encore une fois sur les modèles C ++ dans les microcontrôleurs

introduction

L'idée d'utiliser des modèles C ++ pour la programmation de contrôleurs n'est pas nouvelle; il existe beaucoup de matériel disponible sur le Web. Permettez-moi de rappeler brièvement les principaux avantages: transférer une partie importante des erreurs de l'exécution à la compilation en raison d'un contrôle de type strict, ainsi qu'une approximation d'une approche orientée objet, qui est proche et pratique pour beaucoup, sans qu'il soit nécessaire de stocker les champs dans une classe statique (tous les champs sont des paramètres de modèle). Cependant, il convient de noter que presque tous les auteurs se limitent dans leurs travaux à des exemples d'utilisation des registres et des ports d'E / S. Dans mon article, je souhaite poursuivre ces idées.





Tu ne peux pas être un peu enceinte

La programmation orientée objet implique la présence de classes dans un programme qui interagissent les unes avec les autres. L'interaction s'exprime par la dépendance de certaines classes à d'autres. Et ici l'essence de l'en-tête apparaît: pour passer un modèle de classe B avec des méthodes statiques à la classe A en tant que paramètre , alors la classe B doit également être faite de modèle, et ainsi de suite tout au long de la chaîne.





Par exemple, USART dépend au moins de ses registres, alors la déclaration de la classe correspondante ressemblera à quelque chose comme ça (le code associé à la déclaration des registres est pris d'ici pour assurer la cohérence des articles, merci @lamerok pour les matériaux sympas et exemples. Je ne leur ai pas transmis de wrappers, mais je prévois de le faire.):





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



Nous avons déterminé les registres afin de déclarer une instance UART spécifique, vous devez spécialiser le modèle





using Usart1 = Usart<USART1>;
      
      



Tout semble bien, mais en fait, une interface USART spécifique a différentes dépendances:





  1. Registre d'horloge (RCC_APB2).





  2. Numéro d'interruption.





  3. Un ensemble de broches possibles (Tx et Rx).





  4. Dma (Tx et 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