Easyelectronics.ru

Электроника для всех
Текущее время: 26 май 2020, 00:04

Часовой пояс: UTC + 5 часов



JLCPCB – Прототипы печатных плат за $2/10pcs (Любой цвет!)
Крупнейший производитель печатных плат и прототипов. Более 600000 клиентов и свыше 10000 заказов в день!
Получите скидку на почтовую отправку при первом заказе в JLCPCB!

Начать новую тему Ответить на тему  [ Сообщений: 87 ]  На страницу Пред.  1, 2, 3, 4
Автор Сообщение
 Заголовок сообщения: Re: STM32+SEGGER+FreeRTOS+C++
СообщениеДобавлено: 08 июл 2019, 10:57 
Старожил

Зарегистрирован: 08 июл 2013, 17:00
Сообщения: 485
Ждать семафор не нужно. Можно просто из обработчика прерывания переключиться на задачу, которая остановлена на семафоре. Задача-парсерс останавливается ядром ОС на предварительно заблокированном семафоре, а из обработчика прерывания ядру делается запрос на переключение контекста на остановленную задачу. И всё. У Курницына это хорошо описано, почитай.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: STM32+SEGGER+FreeRTOS+C++
СообщениеДобавлено: 08 июл 2019, 11:49 
Старожил

Зарегистрирован: 06 июн 2018, 22:30
Сообщения: 520
Откуда: Киев
Как-то давно я делал что-то похожее, но просто в виде массива и в виде обычного класса со статическими функциями без наследования и прочего (из-за незнания с++). Хочу сказать что эту часть можно выкинуть:
Код:
extern "C"
{
    //--------------------------------------------------------------------------
    void WWDG_IRQHandler( void )
    {
        callHandler( WWDG_IRQn );
    }
    //--------------------------------------------------------------------------
    void PVD_IRQHandler( void )
    {
        callHandler( PVD_IRQn );
    }
    //--------------------------------------------------------------------------
    void TAMP_IRQHandler( void )
    {
        callHandler( TAMP_STAMP_IRQn );
    }
    //--------------------------------------------------------------------------
    void RTC_WKUP_IRQHandler( void )
    {
        callHandler( RTC_WKUP_IRQn );
    }
    //--------------------------------------------------------------------------
    void FLASH_IRQHandler( void )
    {
        callHandler( FLASH_IRQn );
    }
    //--------------------------------------------------------------------------
    void RCC_IRQHandler( void )
    {
        callHandler( RCC_IRQn );
    }
    //--------------------------------------------------------------------------
    void EXTI0_IRQHandler( void )
    {
        callHandler( EXTI0_IRQn );
    }
    //--------------------------------------------------------------------------

......

Кортексы кроме М0, знают номер текущего обработчика, я просто задавал в стартапе вместо DefaulHandler свою функцию типа этой:
Код:
void callHandler( IRQn_Type _IRQn )
{
    if( handler[ _IRQn ] )
        (( IRQ* )handler[ _IRQn ]) -> IRQ_Handler();
    else
        abort();
}

проверял не NULL ли ссылка и переходил, также я добавил кроме стандартных прерываний еще и свои в конец списка, разделив обработчик на части, если он имел источник от нескольких периферийных модулей или логически так было удобнее (например работа с таймерами). А сам такой обработчик делал статической функцией, там разбирал флаги и переходил опять по таблице. Но как-то совсем не прижилось оно... пишу на простом С.
С виртуальными конечно должно быть красивее и удобнее.
А как быть если периферии нужно несколько обработчиков, ну или классу, мы то наследуем один.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: STM32+SEGGER+FreeRTOS+C++
СообщениеДобавлено: 08 июл 2019, 11:56 
Старожил
Аватара пользователя

Зарегистрирован: 26 окт 2013, 07:58
Сообщения: 2566
tonyk писал(а):
Ждать семафор не нужно. Можно просто из обработчика прерывания переключиться на задачу, которая остановлена на семафоре. Задача-парсерс останавливается ядром ОС на предварительно заблокированном семафоре, а из обработчика прерывания ядру делается запрос на переключение контекста на остановленную задачу. И всё. У Курницына это хорошо описано, почитай.

Я так и делаю


Код:

  xSemaphoreGiveFromISR( xUsartSemaphore, &xHigherPriorityTaskWoken );
              if (xHigherPriorityTaskWoken != pdFALSE)
              {
                  portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
            //    }
              }


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: STM32+SEGGER+FreeRTOS+C++
СообщениеДобавлено: 08 июл 2019, 12:09 
Старожил

Зарегистрирован: 08 июл 2013, 17:00
Сообщения: 485
Выкидывать ничего не нужно!
Во-первых, обрати внимание, что callHandler()-у передаётся номер прерывания, из которого он вызывается:
Код:
extern "C"
{
    //--------------------------------------------------------------------------
    void WWDG_IRQHandler( void )
    {
        callHandler( WWDG_IRQn );
    }
    //--------------------------------------------------------------------------
......


Этот номер может быть передан методу-обработчику прерывания, чтобы тот мог сразу перейти на анализ флагов от конкретного периферийного устройства. То есть, если тебе нужно, то можно сделать так:
Код:
////////////БЫЛО///////////////////////
void callHandler( IRQn_Type _IRQn )
{
    if( handler[ _IRQn ] )
        (( IRQ* )handler[ _IRQn ]) -> IRQ_Handler();
    else
        abort();
}

////////////СТАЛО///////////////////////
void callHandler( IRQn_Type _IRQn )
{
    if( handler[ _IRQn ] )
        (( IRQ* )handler[ _IRQn ]) -> IRQ_Handler( _IRQn );
    else
        abort();
}

Разумеется, исправив сигнатуру у IRQ_Handler(). Здесь я просто не реализовал это.
Цитата:
А как быть если периферии нужно несколько обработчиков, ну или классу, мы то наследуем один.


Очень просто!
Код:
class IRQ
{
    protected:

        //----------------------------------------------------------------------
        // Обработчик прерывания.
        virtual void IRQ_Handler( void ) = 0;

        int installInterruptHandler
        (
            #ifdef __STM32__
               
                IRQn_Type   IRQn    // See "stm32fxxx.h", enum IRQn_Type.

            #endif
        );
                                                     
        int uninstallInterruptHandler
        (
            #ifdef __STM32__
               
                IRQn_Type   IRQn    // See "stm32fxxx.h", enum IRQn_Type.

            #endif
        );

Ты можешь поставить на ЛЮБОЕ прерывание свой обработчик. Хоть на все прерывания сразу! Вот зачем полезно передавать обработчику номер прерывания, из которого ты в него зашёл. Вот почему не нужно ничего выбрасывать!


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: STM32+SEGGER+FreeRTOS+C++
СообщениеДобавлено: 08 июл 2019, 14:27 
Старожил

Зарегистрирован: 06 июн 2018, 22:30
Сообщения: 520
Откуда: Киев
Идея интересная нужно попробовать. Почему-то я сразу подумал что static void *handler[ maxInterruptHandlers ] для хранения ссылок на обработчики. Нужно подумать будет ли выгода от переноса таблицы прерываний в СОЗУ (в данном случае то вроде как и нет).

tonyk Я вижу для себя выгоду использования с++, например можно быстро и легко создать хоть 10 экземпляров класса для работы с USART. Но все ++ перечеркивает то что работа с обработчиками прерываний для разных USART (работа с флагами) очень разная и универсально сделать бывает невозможно, тот же ДМА. Как ты борешся с этим?
P.S. как буду дома покажу как я делал, про выбрасывание вызовов callHandler( ххх);


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: STM32+SEGGER+FreeRTOS+C++
СообщениеДобавлено: 08 июл 2019, 15:01 
Старожил

Зарегистрирован: 23 янв 2016, 15:37
Сообщения: 1168
tonyk писал(а):
Код:
int installInterruptHandler(IRQn_Type IRQn)
{
    if(_IRQn >= 0 || _IRQn < (IRQn_Type)maxInterruptHandlers)
    ....
}

Здесь должно быть &&, в нормальной IDE это условие должно подчеркнуть...


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: STM32+SEGGER+FreeRTOS+C++
СообщениеДобавлено: 08 июл 2019, 16:11 
Старожил

Зарегистрирован: 08 июл 2013, 17:00
Сообщения: 485
Reflector писал(а):
tonyk писал(а):
Код:
int installInterruptHandler(IRQn_Type IRQn)
{
    if(_IRQn >= 0 || _IRQn < (IRQn_Type)maxInterruptHandlers)
    ....
}

Здесь должно быть &&, в нормальной IDE это условие должно подчеркнуть...

Да. Смахнул нечаянно при копи-пасте. Очень приятно, что внимательно смотрят на то, что я пишу.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: STM32+SEGGER+FreeRTOS+C++
СообщениеДобавлено: 08 июл 2019, 17:27 
Старожил

Зарегистрирован: 23 янв 2016, 15:37
Сообщения: 1168
MasterElectric писал(а):
Но все ++ перечеркивает то что работа с обработчиками прерываний для разных USART (работа с флагами) очень разная и универсально сделать бывает невозможно, тот же ДМА.

Какая проблема с DMA и флагами?
Код:
template<uint32_t Stream, uint32_t Channel, IRQn_Type Irqn>
class DmaStream
{
public:
   static _inline_ auto dma() { return (DMA_TypeDef*)dmaBase; }
   static _inline_ auto stream() { return (DMA_Stream_TypeDef*)Stream; }

   static void clearFlags(DmaFlag flags)
   {
      if constexpr(shift < 64)
         dma()->LIFCR = uint32_t(flags) << (shift & 0x1F);
      else
         dma()->HIFCR = uint32_t(flags) << (shift & 0x1F);
   }
   ......

private:
   static constexpr uint32_t dmaBase = Stream & 0xFFFF'FF00;
   static constexpr uint32_t streamNum = (Stream & 0xFF) / 24;
   static constexpr uint32_t arr[] = { 0, 6, 16, 22, 64, 70, 80, 86 };
   static constexpr uint32_t shift = arr[streamNum];
};

template<uint32_t Channel = 0>
using Dma1Stream0 = DmaStream<DMA1_Stream0_BASE, Channel, DMA1_Stream0_IRQn>;
....


Последний раз редактировалось Reflector 08 июл 2019, 17:40, всего редактировалось 1 раз.

Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: STM32+SEGGER+FreeRTOS+C++
СообщениеДобавлено: 08 июл 2019, 17:31 
Старожил

Зарегистрирован: 08 июл 2013, 17:00
Сообщения: 485
MasterElectric писал(а):
tonyk Но все ++ перечеркивает то что работа с обработчиками прерываний для разных USART (работа с флагами) очень разная и универсально сделать бывает невозможно, тот же ДМА.

А нет никакой проблемы. Смотри:
Код:
////////////////////////////////////////////////////////////////////////////////

class AbsUART : public AbstractTransport, public IRQ
{
   .....................

    protected:

    ........................
       
        #ifdef __STM32__
       
            USART_TypeDef*  usart;

            //------------------------------------------------------------------
            // Устанавливает события, по которым будет формироваться прерывания.
            // Не забудь установить UE и определись с RE и TE!
            virtual void setEvents( void ) = 0;

        #endif

Код:
////////////////////////////////////////////////////////////////////////////////

class IRQ
{
    protected:

        //----------------------------------------------------------------------
        // Обработчик прерывания.
        virtual void IRQ_Handler( void ) = 0;

       ......................

То есть в методе setEvents() я настраиваю регистры под конкретный режим. Выше я писал:
Цитата:
Даже если приспичит на ходу переключаться из консоли в режим Модбаса, то просто порождается наследник от консоли и Модбаса, который в зависимости от режима работы вызывает методы обработки того или иного своего предка.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: STM32+SEGGER+FreeRTOS+C++
СообщениеДобавлено: 09 июл 2019, 12:19 
Заглядывает иногда

Зарегистрирован: 25 янв 2012, 20:51
Сообщения: 78
У меня ISR'ы прописаны так
Всё работает как часы, чистый C++


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: STM32+SEGGER+FreeRTOS+C++
СообщениеДобавлено: 09 июл 2019, 13:06 
Старожил

Зарегистрирован: 08 июл 2013, 17:00
Сообщения: 485
andreil писал(а):
У меня ISR'ы прописаны так
Всё работает как часы, чистый C++

Только это не ООП... Обычный "С", переписанный на синтаксисе "С++".
Код:
void STM32_UART::init_all()
{
    #ifdef STM32_USE_UART1
    uart1.m_uart = USART1;
    uart1.m_busy = false;
    #endif
    #ifdef STM32_USE_UART2
    uart2.m_uart = USART2;
    uart2.m_busy = false;
    #endif
    #ifdef STM32_USE_UART3
    uart3.m_uart = USART3_;
    uart3.m_busy = false;
    #endif
    #ifdef STM32_USE_UART4
uart4.m_uart = UART4;

Код:

class STM32_UART
{
public:
    static void init_all();
    void init(uint32_t brate);
    void deinit();
   
    void send_char(char ch);
    void send_str(const char *str, TXRX_MODE mode);
    void send_buf(const char *buf, int size, TXRX_MODE mode);

   void irq_proc();
private:
    USART_TypeDef*  m_uart;
    uint32_t        m_brate;
    volatile bool   m_busy;

    void set_baud_rate(uint32_t brate);
    void set_config();
   
   void recv_data();
   void send_data();

   char   m_rx_buf[UART_BUF_SIZE];
   int      m_rx_size;
   int      m_rx_pos;

   char   m_tx_buf[UART_BUF_SIZE];
   int      m_tx_size;
   int      m_tx_pos;
};

extern STM32_UART uart1;
extern STM32_UART uart2;
extern STM32_UART uart3;
extern STM32_UART uart4;
extern STM32_UART uart5;
extern STM32_UART uart6;
extern STM32_UART uart7;
extern STM32_UART uart8;


А это просто лень? Или незнание?
Код:
#define UART_BRR (F_CPU / BRATE)

Должно быть примерно так:
Код:
uint32
        floor = SystemCoreClock / ( APB_divider * (uint32)_baudRate * 16UL );

    int32 
        frac =
            (
                ( SystemCoreClock / APB_divider ) -
                ( (uint32)_baudRate * floor * 16UL )
            ) / 200L,

        fracfrac = frac % 100L;

    frac /= 100L;

    if( fracfrac > 50 )
        ++frac;

    usart -> BRR = ( floor << 4 ) | frac;   // Выставили делитель.



Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: STM32+SEGGER+FreeRTOS+C++
СообщениеДобавлено: 09 июл 2019, 13:49 
Старожил

Зарегистрирован: 23 янв 2016, 15:37
Сообщения: 1168
andreil писал(а):
Всё работает как часы, чистый C++

Это все нужно выбросить и переписать с нуля... Как вообще можно было додуматься сразу создавать экземпляры чуть ли не всей имеющейся периферии... И ошибок полно, взять тот же обсуждаемый в этой теме кольцевой буфер, он у тебя не в виде класса, без volatile, с размером, без критических секций. Это никак не может работать правильно, оно будет работать только при определенных условиях. Даже несчастный пин оторван от номера пина, внутри класса хранит указатель на gpio и при записи в порт юзает ODR...


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 87 ]  На страницу Пред.  1, 2, 3, 4


Часовой пояс: UTC + 5 часов


Кто сейчас на конференции

Сейчас этот форум просматривают: BARS_, Eddy_Em


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB