Easyelectronics.ru

Электроника для всех
Текущее время: 22 авг 2019, 08:26

Часовой пояс: 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
Сообщения: 172
Ждать семафор не нужно. Можно просто из обработчика прерывания переключиться на задачу, которая остановлена на семафоре. Задача-парсерс останавливается ядром ОС на предварительно заблокированном семафоре, а из обработчика прерывания ядру делается запрос на переключение контекста на остановленную задачу. И всё. У Курницына это хорошо описано, почитай.


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

Зарегистрирован: 06 июн 2018, 22:30
Сообщения: 410
Откуда: Киев
Как-то давно я делал что-то похожее, но просто в виде массива и в виде обычного класса со статическими функциями без наследования и прочего (из-за незнания с++). Хочу сказать что эту часть можно выкинуть:
Код:
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
Сообщения: 2311
tonyk писал(а):
Ждать семафор не нужно. Можно просто из обработчика прерывания переключиться на задачу, которая остановлена на семафоре. Задача-парсерс останавливается ядром ОС на предварительно заблокированном семафоре, а из обработчика прерывания ядру делается запрос на переключение контекста на остановленную задачу. И всё. У Курницына это хорошо описано, почитай.

Я так и делаю


Код:

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


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

Зарегистрирован: 08 июл 2013, 17:00
Сообщения: 172
Выкидывать ничего не нужно!
Во-первых, обрати внимание, что 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
Сообщения: 410
Откуда: Киев
Идея интересная нужно попробовать. Почему-то я сразу подумал что static void *handler[ maxInterruptHandlers ] для хранения ссылок на обработчики. Нужно подумать будет ли выгода от переноса таблицы прерываний в СОЗУ (в данном случае то вроде как и нет).

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


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

Зарегистрирован: 23 янв 2016, 15:37
Сообщения: 988
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
Сообщения: 172
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
Сообщения: 988
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
Сообщения: 172
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
Сообщения: 76
У меня ISR'ы прописаны так
Всё работает как часы, чистый C++


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

Зарегистрирован: 08 июл 2013, 17:00
Сообщения: 172
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
Сообщения: 988
andreil писал(а):
Всё работает как часы, чистый C++

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


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

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


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

Сейчас этот форум просматривают: нет зарегистрированных пользователей


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

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

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