Skip to Content

RingBuffer для embedded

Долго терпел но всё-таки порвало и решил набросать маленький template для кольцевого буфера чуток оптимизированный для экономии ОЗУ. Вот его сырая версия. Если будет настроение то доделаю.

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

А вот и долгожданный template в прикреплённом файле :)

ПредпросмотрВложениеРазмер
ring_buff.txt3.52 КБ

Комментарии

Настройки просмотра комментариев

Выберите нужный метод показа комментариев и нажмите "Сохранить установки".

natyazhnye-potolki-ufallFed

Выбирая оформление верха для ресторан либо заведение надо обратить интерес на разнообразные вариацию подвисных волокон, что достаточно практичны, хороши и визуально привлекательные. В данный час http://natyazhnye-potolki-ufa.com именно на бирже рекомендуют огромный комплект натяжных поверхностей из доброкачественного фурнитуры, какой произведет убранство вашего места роскошным также современным. Наша фирма касательно исполнении, промышленности и монтаже эко ткани подносит пользователям гарнитуру виниловых материала отменного типа с винильного материала содержания, глянца, жесткого также лоснистого ткани, покрова, 2 уровневые плюс иные лишние возможности - свет, фотообои, отражатели. Непосредственно на веб-странице компании натяжные потолки фото заказчик получает возможность выбрать эластичные потолки у сходными стоимостью также регулярными предложениями, команда квалитативных профессионалов указывает фирменную монтаж у длении сорока восьми часов спустя покупки, исправность также бесплатные ответы. Указать расценки, просмотреть разработанные опыт, найти современный ткань возможно прямо на определенном сайте в всякое период дня.

natyazhnye-potolki-ufallFed

Выбирая оформление верха для ресторан либо заведение надо обратить интерес на разнообразные вариацию подвисных волокон, что достаточно практичны, хороши и визуально привлекательные. В данный час http://natyazhnye-potolki-ufa.com именно на бирже рекомендуют огромный комплект натяжных поверхностей из доброкачественного фурнитуры, какой произведет убранство вашего места роскошным также современным. Наша фирма касательно исполнении, промышленности и монтаже эко ткани подносит пользователям гарнитуру виниловых материала отменного типа с винильного материала содержания, глянца, жесткого также лоснистого ткани, покрова, 2 уровневые плюс иные лишние возможности - свет, фотообои, отражатели. Непосредственно на веб-странице компании натяжные потолки фото заказчик получает возможность выбрать эластичные потолки у сходными стоимостью также регулярными предложениями, команда квалитативных профессионалов указывает фирменную монтаж у длении сорока восьми часов спустя покупки, исправность также бесплатные ответы. Указать расценки, просмотреть разработанные опыт, найти современный ткань возможно прямо на определенном сайте в всякое период дня.

european-yachtsput

Самое приметное впечатление ото релакса, это же наверняка туризм с дорогим человеком или семьей определенно на изумительной яхте на местах существующих морей, поездка что легко и просто возможно расположить у вашей жизни с пособием сервиса данной конторы. данная предпринимательство снабжает все необходимые сервис по аренды яхт именно на Эгейском, Средиземном, Балтийском, Карибском, Ионическом плюс других морях. определенно здесь пользователь сможете сделать специально для группой курорт по приемлемыми ценам и широким выбором предписанием: сформировать круиз лишь на пару дней, пару недель, 4 недели, подобрать необычный путь, составить умелую бригаду заодно из капитаном, протокол всех главной документов, помощь в получении яхты, инженерный диагностика на исправность . Компания именно по чартеру яхт презентует клиентам уютные двигательные и аксельные судна любых масштабов и рода цены в США, Канаде, Таиланде, Турции, Карибах, Франции, Польше, Греции и других локациях. только на официальном источнике организации аренда яхты родос http://european-yachts.com/rent-yacht-greece заказчик сможет получить любые контактные сведения непосредственно для соединения, обозреть фотоотчет, парк судна и прочитать отзывы ото заказчиков. С желанием ожидаем ваши звонков также заявок.

european-yachtsput

Самое приметное впечатление ото релакса, это же наверняка туризм с дорогим человеком или семьей определенно на изумительной яхте на местах существующих морей, поездка что легко и просто возможно расположить у вашей жизни с пособием сервиса данной конторы. данная предпринимательство снабжает все необходимые сервис по аренды яхт именно на Эгейском, Средиземном, Балтийском, Карибском, Ионическом плюс других морях. определенно здесь пользователь сможете сделать специально для группой курорт по приемлемыми ценам и широким выбором предписанием: сформировать круиз лишь на пару дней, пару недель, 4 недели, подобрать необычный путь, составить умелую бригаду заодно из капитаном, протокол всех главной документов, помощь в получении яхты, инженерный диагностика на исправность . Компания именно по чартеру яхт презентует клиентам уютные двигательные и аксельные судна любых масштабов и рода цены в США, Канаде, Таиланде, Турции, Карибах, Франции, Польше, Греции и других локациях. только на официальном источнике организации аренда яхты родос http://european-yachts.com/rent-yacht-greece заказчик сможет получить любые контактные сведения непосредственно для соединения, обозреть фотоотчет, парк судна и прочитать отзывы ото заказчиков. С желанием ожидаем ваши звонков также заявок.

virtual-local-numbers

In my opinion you commit an error. I suggest it to discuss. Write to me in PM. ----- france did number

continent-telecomDyday

включение услуги "воображаемого цифр" очень доступное для многих личностей, что держат коммерцию также нарабатывают дельных партнеров около всему миру, натурально данные личности всегда обязанны состоять на телефона. Вы еще не понимаете, как же получается стань популярным торговым- предпринимателем , совершать дела у иных городах также уделять отдхыд близким? Тогда для вас немедленно труюуется подключить прямым условную сеть. С помощью описанной сервиса вы сможете покрыть себя и личную компанию постоянной мобильной связью, так как при включении возможного номера вы покупает код телефона требуемой для вас державы: Китайской империи, Соединенных Штатов, Великобритания, также иных государств, наша компания предоставляем более девяносто государств в ваше распоряжение. Используя услугу, потребитель лишается от лишних расходов, утрата важных клиентов также час на постоянных визитов. Взамен у вас есть: непрерывная звонки с вашими товарищами и потребителями, благодаря кода все думают, что вы сидите у предполагаемом офисе, хотя вы имеете способность ездить в прогулку с семьей либо у своем основном отделении, прием многих вызовов сразу, статистика вызовов, удобная переадресация на мобильный, центрального, стационарный, скайп -номера, сохранение шрифта при переправы также развитие по все местам собственных филий около всему миру. данная фирма внешней звонков британские телефонные номера показывает для наших клиентов услуги покупки условного страны под любого предназначения, систематическую порядок использования и мобильную консультацию ото наших операторов, из виртуальным номером ваша дело станет полезным и удобной для клиента также любое промышленность.

говнокод!

До осваивания C++ стоило бы научиться отделять мух от котлет (регистры AT91SAM7xxx от шаблона).

А собственно никакой реализации fifo и не увидел, вчитавшись. Доставляет также блокирующий Write. Из неблокирующего сделать блокирующий простым применением while() всегда можно и это стоит оставить для самого верхнего уровня.

Собственно это был комментарий к тому, что внизу страницы. Если говорить и том, что выше -- без 0.5 не разобраться.

Имею аналогичный код, тоже в виде "шаблона" (что разменивает больший объём программной памяти на более высокую скорость, если уартов больше одного, а иначе просто быстрей и компактней) на голом C -- весь код рассован по-макросам. Прошло много времени, много разных MCU и проектов. И пришла в голову очевидная мысль, что вообще реализацию fifo следует отделить от "драйвера UART-модуля". Ибо последние очень уж разные. Что для 8-битников врукопашную, то для больших MCU очень сильно не так. А при наличии ОС и вовсе fifo не особо нужно (ибо своё наличествует, в драйвере).

Считаю, в проекте без ОС нужны 3 вещи: "драйвер" непосредстенно к модулю UART микроконтроллера, побайтовое быстрое fifo, и прослойка между этим всем и программой. Последние 2 вещи аппаратно-независимые вообще. Прослойка для программной реализации CTS/RTS (если в контроллере нет) и т.п. вещей, а также для приведения интерфейса близкого к виндовому/линуховому.

PS: да, блокировка по IP тоже доставляет.

[ZX]

>> До осваивания C++ стоило

>> До осваивания C++ стоило бы научиться отделять мух от котлет (регистры AT91SAM7xxx от шаблона).

Это шаблон драйвера UART SAM9XE это раз по этому мухи и котлеты на своих местах,

 

>> А собственно никакой реализации fifo и не увидел

Ее там и нету, это моя ошибка, хотел дать ответ на

 >> C++ with templates иEmbedded?

>> Какое-то странное сочетание...

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

>>И пришла в голову очевидная мысль, что вообще реализацию fifo следует отделить от "драйвера UART-модуля"

В моем модуле так и сделано только в качестве буфера выступает PDC вот реализация кто знаком с архитектурой AT91SAM9XE тот поймет, этот код можно прилепить к любой периферии проца которая имеет PDC. Что и сделано в моем коде:

 typedef THwTXPDC<PORT,TX_BUFF_SIZE> TxFIFO; //FIFO передачи
 typedef THwRXPDC<PORT,RX_BUFF_SIZE> RxFIFO; //FIFO приема

Если сильно интересно прилагаю шаблон класса реализующего обмен через PDC с периферией. В текущей версии реализация только для UART

#ifndef __HwPDC_H__
#define __HwPDC_H__

#include <cstdint>
#include <cstring>
#include "AT91SAM9XE512.h"

template <int ID,int TSIZE>
class THwTXPDC
{
  protected:
    static uint8_t* tx_data_ptr;
    static uint8_t  tx_buff[TSIZE] @ ".not_cached";
    /******************************************************************************
    * FUNCTION:     PDC_BASE
    *
    * DESCRIPTION:  
    * PARAMETERS:   
    * RETURNS:      
    *
    ******************************************************************************/
    inline static volatile AT91S_PDC *PDC_BASE()
    {
      switch (ID)
      {
        case AT91C_ID_US0: return AT91C_BASE_PDC_US0;
        case AT91C_ID_US1: return AT91C_BASE_PDC_US0;
        case AT91C_ID_US2: return AT91C_BASE_PDC_US0;
        case AT91C_ID_US3: return AT91C_BASE_PDC_US0;
        case AT91C_ID_US4: return AT91C_BASE_PDC_US0;
        case AT91C_ID_SYS: return AT91C_BASE_PDC_DBGU;
      
		        //todo: дописать идентификаторы остальной периферии
	
        default:           return NULL;
      }
    };
  public:
    enum
    {
      SIZE  = TSIZE
    };
    /******************************************************************************
    * FUNCTION:     TXBUFE_Handler
    *
    * DESCRIPTION:  
    * PARAMETERS:   
    * RETURNS: true - если надо отключить прерывания      
    *
    ******************************************************************************/
    inline static uint32_t TXBUFE_Handler(void)
    {
      uint32_t size;
      uint8_t *pdc_addr = reinterpret_cast<uint8_t*>(PDC_BASE()->PDC_TPR); //Warning[Pe1053]: conversion from integer to smaller pointer
      PDC_BASE()->PDC_TPR  = reinterpret_cast<uint32_t>(pdc_addr); 
      if (tx_data_ptr >= pdc_addr)
      {
        size = (tx_data_ptr - pdc_addr);
      }
      else
      {
        size = SIZE - (pdc_addr - tx_data_ptr);
      }
      if ( size )
      {
        if (( pdc_addr + size) <= &tx_buff[SIZE])
        {
          PDC_BASE()->PDC_TCR = size;
        }
        else
        {
          PDC_BASE()->PDC_TCR  = reinterpret_cast<uint32_t>(&tx_buff[SIZE]) -  reinterpret_cast<uint32_t>(pdc_addr);
          PDC_BASE()->PDC_TNPR = reinterpret_cast<uint32_t>(tx_buff);
          PDC_BASE()->PDC_TNCR = size - (reinterpret_cast<uint32_t>(&tx_buff[SIZE]) - reinterpret_cast<uint32_t>(pdc_addr));
        }
      }
      return size;
    };
    /******************************************************************************
    * FUNCTION:     Enable
    *
    * DESCRIPTION:  
    * PARAMETERS:   
    * RETURNS:      
    *
    ******************************************************************************/    
    static void Init(void)
    {
      PDC_BASE()->PDC_PTCR = AT91C_PDC_TXTDIS;
      tx_data_ptr          = tx_buff;
      PDC_BASE()->PDC_TPR  = reinterpret_cast<uint32_t>(tx_buff);
      PDC_BASE()->PDC_TCR  = 0;
      PDC_BASE()->PDC_TNCR = 0;
      PDC_BASE()->PDC_PTCR = AT91C_PDC_TXTEN;
    }
    /******************************************************************************
    * FUNCTION:     Disable
    *
    * DESCRIPTION:  
    * PARAMETERS:   
    * RETURNS:      
    *
    ******************************************************************************/
    static void DeInit(void)
    {
      while((PDC_BASE()->PDC_TCR !=0) || (PDC_BASE()->PDC_TNCR !=0));
      PDC_BASE()->PDC_PTCR = AT91C_PDC_TXTDIS;
    }
    /******************************************************************************
    * FUNCTION:     Free
    *
    * DESCRIPTION:  
    * PARAMETERS:   
    * RETURNS:      
    *
    ******************************************************************************/
    static uint_fast16_t Free(void)
    {
      uint8_t* pdc_addr = reinterpret_cast<uint8_t*>(PDC_BASE()->PDC_TPR);
      if ( tx_data_ptr >= pdc_addr )
      {
        return (SIZE-1) - (tx_data_ptr - pdc_addr);
      }
      else
      {
        return (pdc_addr - tx_data_ptr)-1;
      }
    }
    /******************************************************************************
    * FUNCTION:     Write
    *
    * DESCRIPTION:  
    * PARAMETERS:   
    * RETURNS:      
    *
    ******************************************************************************/
    static uint32_t Write(const uint8_t* data, uint_fast16_t size)
    {
      uint32_t ssize,txfree;
      uint8_t const *ptr = data;
      txfree = Free();
      ssize = (txfree >= size)?size:txfree;
      if((tx_data_ptr + ssize) < &tx_buff[SIZE])
      {
        memcpy(tx_data_ptr,ptr,ssize);
        tx_data_ptr += ssize;
      }
      else
      {
        uint32_t L_size = &tx_buff[SIZE] - tx_data_ptr;  
        memcpy(tx_data_ptr,ptr,L_size);
        uint32_t Rrsize = ssize - L_size;   
        memcpy(tx_buff,(ptr+L_size),Rrsize); 
        tx_data_ptr = tx_buff + Rrsize;
      }
      return ssize;
    };
};

template <int ID, int TSIZE> 
uint8_t* THwTXPDC<ID,TSIZE>::tx_data_ptr;

template <int ID, int TSIZE> 
uint8_t THwTXPDC<ID,TSIZE>::tx_buff[TSIZE];


template <int ID,int TSIZE>
class THwRXPDC
{
protected:
    static uint8_t* rx_data_ptr;
    static uint8_t  rx_buff[TSIZE] @ ".not_cached";
    /******************************************************************************
    * FUNCTION:     PDC_BASE
    *
    * DESCRIPTION:  
    * PARAMETERS:   
    * RETURNS:      
    *
    ******************************************************************************/
    inline static volatile AT91S_PDC *PDC_BASE()
    {
      switch (ID)
      {
        case AT91C_ID_US0: return AT91C_BASE_PDC_US0;
        case AT91C_ID_US1: return AT91C_BASE_PDC_US0;
        case AT91C_ID_US2: return AT91C_BASE_PDC_US0;
        case AT91C_ID_US3: return AT91C_BASE_PDC_US0;
        case AT91C_ID_US4: return AT91C_BASE_PDC_US0;
        case AT91C_ID_SYS: return AT91C_BASE_PDC_DBGU;
        default:           return NULL;
      }
    };
  public:
    enum
    {
      SIZE  = TSIZE
    };
    /******************************************************************************
    * FUNCTION:     PDC_BASE
    *
    * DESCRIPTION:  
    * PARAMETERS:   
    * RETURNS:      
    *
    ******************************************************************************/
    static void Init(void)
    {
      PDC_BASE()->PDC_PTCR = AT91C_PDC_RXTDIS;
      rx_data_ptr = rx_buff;
      PDC_BASE()->PDC_RPR   = reinterpret_cast<uint32_t>(rx_buff);
      PDC_BASE()->PDC_RCR   = SIZE-1;
      PDC_BASE()->PDC_RNCR  = 0;
      PDC_BASE()->PDC_PTCR = AT91C_PDC_RXTEN;
    };
    /******************************************************************************
    * FUNCTION:     TXBUFE_Handler
    *
    * DESCRIPTION:  
    * PARAMETERS:   
    * RETURNS: true - если надо отключить прерывания      
    *
    ******************************************************************************/
    inline static uint32_t RXBUFF_Handler(void)
    {
      uint32_t size;
      uint8_t *pdc_addr = reinterpret_cast<uint8_t*>(PDC_BASE()->PDC_RPR);
      if ( pdc_addr ==  &rx_buff[SIZE])
      {
        pdc_addr = rx_buff;
      };
      PDC_BASE()->PDC_RPR  = reinterpret_cast<uint32_t>(pdc_addr);    
      if ( rx_data_ptr > pdc_addr)
      {
        size = (rx_data_ptr - pdc_addr) - 1;
      }
      else
      {
        size = ((SIZE + rx_data_ptr) - pdc_addr) - 1;       
      }
      if( size )
      {
        if (( size + pdc_addr ) <= &rx_buff[SIZE] )
        {
          PDC_BASE()->PDC_RCR  = size;
        }
        else
        {
          PDC_BASE()->PDC_RCR  = &rx_buff[SIZE] - pdc_addr;
          PDC_BASE()->PDC_RNPR = reinterpret_cast<uint32_t>(rx_buff);
          PDC_BASE()->PDC_RNCR = size - (&rx_buff[SIZE] - pdc_addr);
        }
      }
      return size;
    }
    /******************************************************************************
    * FUNCTION:     TXBUFE_Handler
    *
    * DESCRIPTION:  
    * PARAMETERS:   
    * RETURNS: true - если надо отключить прерывания      
    *
    ******************************************************************************/
    static uint_fast16_t Recived(void)
    {
      uint32_t size;
      uint8_t *pdc_addr = reinterpret_cast<uint8_t*>(PDC_BASE()->PDC_RPR);
      size = (pdc_addr >= rx_data_ptr)?pdc_addr - rx_data_ptr:(SIZE + (pdc_addr - rx_data_ptr));
      return size;
    }
    /******************************************************************************
    * FUNCTION:     TXBUFE_Handler
    *
    * DESCRIPTION:  
    * PARAMETERS:   
    * RETURNS: true - если надо отключить прерывания      
    *
    ******************************************************************************/
    static uint_fast16_t Read(void *data, uint_fast16_t buff_size)
    {
      uint32_t rsize = Recived();
      uint8_t *ptr = static_cast<uint8_t*>(data); 
      if( rsize > buff_size ) rsize = buff_size;    
      if (( rx_data_ptr + rsize) < &rx_buff[SIZE])
      {
        memcpy(ptr,rx_data_ptr,rsize);
        rx_data_ptr += rsize;
      }
      else
      {
        uint32_t Lrsize = &rx_buff[SIZE] - rx_data_ptr;
        memcpy(ptr,rx_data_ptr,Lrsize);
        uint32_t Rrsize = rsize - Lrsize;
        memcpy(ptr + Lrsize,rx_buff,Rrsize);
        rx_data_ptr = rx_buff + Rrsize;
      }
      return rsize;
    };
};

template <int ID, int TSIZE> 
uint8_t* THwRXPDC<ID,TSIZE>::rx_data_ptr;

template <int ID, int TSIZE> 
uint8_t THwRXPDC<ID,TSIZE>::rx_buff[TSIZE];

#endif



P.S. Еще раз повторю это не демонстрация кода или приемов программирования, это демонстрация того что C++ и шаблоны используются еще как.

Очегнь даже ничего сочитается

	Мой шаблон драйера уартов для SAM9XE могу сказать что никакго оверхеда нету а в некоторых 
случаях код еще быстрее.
/********************************************* COMMON UARTs *****************************************/
template <int PORT, int TX_BUFF_SIZE, int RX_BUFF_SIZE>
class THwUART
{
private:
  static uint32_t last_err;

  typedef THwTXPDC<PORT,TX_BUFF_SIZE> TxFIFO;
  typedef THwRXPDC<PORT,RX_BUFF_SIZE> RxFIFO;

  static inline volatile AT91S_USART  *UART_BASE()
  {
    switch ( PORT )
    {
      case AT91C_ID_US0: return AT91C_BASE_US0;
      case AT91C_ID_US1: return AT91C_BASE_US1;
      case AT91C_ID_US2: return AT91C_BASE_US2;
      case AT91C_ID_US3: return AT91C_BASE_US3;
      case AT91C_ID_US4: return AT91C_BASE_US4;
      default: return NULL;
    }
  }

  static void irq_handler()
  {
    uint32_t status = UART_BASE()->US_CSR; 
    if( status &  AT91C_US_TXBUFE)
    {
      if( TxFIFO::TXBUFE_Handler() == 0)
      {
        UART_BASE()->US_IDR = AT91C_US_TXBUFE;
      }
    }
    if( status &  AT91C_US_RXBUFF)
    {
      if ( RxFIFO::RXBUFF_Handler() == 0 )
      {
        UART_BASE()->US_IDR = AT91C_US_RXBUFF;
      }
    };
    if ( status & (AT91C_US_OVRE | AT91C_US_FRAME | AT91C_US_PARE))
    {
      last_err = UART_BASE()->US_CSR & (AT91C_US_OVRE | AT91C_US_FRAME | AT91C_US_PARE);
      UART_BASE()->US_CR = AT91C_US_RSTSTA;
    }
  };

public:
  enum 
  {
    ID = PORT,
    TXBUFF_SIZE = TX_BUFF_SIZE, 
    RXBUFF_SIZE = RX_BUFF_SIZE
  };
  typedef enum {ERR_OK,ERR_OPEN,ERR_MODE} err_t;

  static err_t Open(const UART::DCB_t &config)
  {
    ....
    return THwUART::ERR_OK;
  };

  static uint32_t LastError(void)
  {
    ...
  }

  static void Write(const void* data, uint_fast16_t len)
  {
    const uint8_t *ptr = static_cast<const uint8_t*>(data);
    while(len)
    {
      uint32_t ssize = TxFIFO::Write(ptr,len);
      UART_BASE()->US_IER = AT91C_US_TXBUFE;
      ptr += ssize;
      len -= ssize;
    }
  }

  static uint_fast16_t Recived(void)
  {
    return RxFIFO::Recived();
  }

  static uint_fast16_t Read(void *data, uint_fast16_t buff_size)
  {
    uint32_t tmp = RxFIFO::Read(data,buff_size);
    if ( tmp )
    {
      UART_BASE()->US_IER = AT91C_US_RXBUFF;
    }
    return tmp;
  }

};

Страннно...

C++ with templates и Embedded?

Какое-то странное сочетание...

Вполне нормально.

Вполне нормально. Вон, scmRTOS чуть менее чем полностью состоит из шаблонов :)

Отправить комментарий

Содержание этого поля является приватным и не предназначено к показу.
  • Syntax highlight code surrounded by the {syntaxhighlighter SPEC}...{/syntaxhighlighter} tags, where SPEC is a Syntaxhighlighter options string or "class="OPTIONS" title="the title".
  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.
  • Доступны HTML теги: <a> <p> <span> <s> <strike> <div> <h1> <h2> <h3> <h4> <h5> <h6> <img> <map> <area> <hr> <br> <br /> <ul> <ol> <li> <dl> <dt> <dd> <table> <caption> <tbody> <tr> <td> <em> <b> <u> <i> <strong> <del> <ins> <sub> <sup> <quote> <blockquote> <pre> <address> <code> <cite> <embed> <object> <param> <strike>
  • Использовать как разделитель страниц.

Подробнее о форматировании

CAPTCHA
Введите текст что Вы видите на картинке. Регистр букв не важен.