реклама на сайте
подробности

 
 
> CAN на STM32F + FreeRTOS
Boriska
сообщение Apr 2 2013, 09:05
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 65
Регистрация: 28-11-07
Пользователь №: 32 772



Пытаюсь обрабатывать входящие сообщения по шине CAN. Хотелось бы чтобы полученные сообщения были гарантированно обработаны, а если ресурсов не хватает, то чтобы они и не были получены.

Если в обработке прерывания просто очистить флаг прерывания и установить семафор, а чтение и очистку почтового ящика (CAN) сделать в отдельной задаче, то ничего не работает. После выхода из прерывания без установки RFOM (очистка ящика), прерывание тут же вызывается снова и задача по чтению сообщения вообще не получает управления.

А если в обработчике очистить флаг прерывания, прочитать и очистить почтовый ящик, то задача обработки получит управления, но тут может возникнуть ситуация, когда сообщение получено, прочитано, но не обработано, поскольку задаче по обработке не хватило ресурсов.
Как можно решить такую задачу?
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов (1 - 4)
Boriska
сообщение Apr 2 2013, 16:42
Сообщение #2


Участник
*

Группа: Участник
Сообщений: 65
Регистрация: 28-11-07
Пользователь №: 32 772



Вот так вот работает:
Код
static void vHandlerCANIRQ( void *pvParameters ){
    uint8_t curPacket;
    
    portBASE_TYPE xStatus;
    for(;; ){
        xStatus = xQueueReceive(xCANQueue, &curPacket, portMAX_DELAY );
        if( xStatus == pdPASS ){
             printf("Data - %d\r\n",RxMessage[curPacket].Data[0]);
                          canRxMessage[curPacket] = 0;
        }
    }
}

    void CAN1_RX0_IRQHandler(void) {
        uint8_t i=0;
        static portBASE_TYPE xHigherPriorityTaskWoken;
        xHigherPriorityTaskWoken = pdFALSE;
        
        if(CAN_GetITStatus(CAN1,CAN_IT_FMP0)!=RESET){
            while((i<CAN_RX_QUEUE_MAX)&&(canRxMessage[i]==1)){
                i++;
            }
            
            if(i<CAN_RX_QUEUE_MAX){
                canRxMessage[i] = 1;
                CAN_Receive(CANx, CAN_FIFO0, &(RxMessage[i]));
                CAN_ClearITPendingBit(CAN1,CAN_IT_FMP0);
                
                xQueueSendFromISR( xCANQueue, &i, &xHigherPriorityTaskWoken );
                if( xHigherPriorityTaskWoken != pdFALSE ){
                    portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
                }
            }else{
                //Lost message
                CAN_FIFORelease(CANx, CAN_FIFO0);
                CAN_ClearITPendingBit(CAN1,CAN_IT_FMP0);
            }

        }
    }


А так не хочет:
Код
static void vHandlerCANIRQ( void *pvParameters ){
    
    for(;; ){
        xSemaphoreTake( xBinarySemaphoreCAN, portMAX_DELAY );
        CAN_Receive(CANx, CAN_FIFO0, &(RxMessage));
        printf("Data - %d\r\n",RxMessage.Data[0]);
                    
    }
}

    void CAN1_RX0_IRQHandler(void) {

        static portBASE_TYPE xHigherPriorityTaskWoken;
        xHigherPriorityTaskWoken = pdFALSE;
        
        if(CAN_GetITStatus(CAN1,CAN_IT_FMP0)!=RESET){
            CAN_ClearITPendingBit(CAN1,CAN_IT_FMP0);
                
            xSemaphoreGiveFromISR( xBinarySemaphoreCAN, &xHigherPriorityTaskWoken );
            if( xHigherPriorityTaskWoken != pdFALSE ){
                portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
            }
            

        }
    }
Go to the top of the page
 
+Quote Post
zebrox
сообщение Apr 5 2013, 16:05
Сообщение #3


Частый гость
**

Группа: Участник
Сообщений: 121
Регистрация: 17-04-09
Пользователь №: 47 838



Задачи должны быть независимы друг от друга. Одна только принимает, другая только обрабатывает. Они вообще не должны знать о сущестровании друг друга.
У обработчика должен быть буфер входящих сообщений. Приемник в него записывает, если при записи нового сообщения буфер заполняется до определенного уровня, то это можно использовать как сигнал для увеличения приоритета обработчика, например, или генерацию аларма делать.
Go to the top of the page
 
+Quote Post
Boriska
сообщение Apr 7 2013, 21:53
Сообщение #4


Участник
*

Группа: Участник
Сообщений: 65
Регистрация: 28-11-07
Пользователь №: 32 772



Цитата(zebrox @ Apr 5 2013, 20:05) *
У обработчика должен быть буфер входящих сообщений. Приемник в него записывает, если при записи нового сообщения буфер заполняется до определенного уровня, то это можно использовать как сигнал для увеличения приоритета обработчика, например, или генерацию аларма делать.

В реализации CAN на STM32 уже есть буфер на 3 входящих сообщения (т.н. почтовые ящики). Почему бы ими не воспользоваться?
Если буфер полностью заполнен, то отправитель, при отправке очередного пакета, не получит подтверждение, что его сообщение доставлено. Это очень удобно. Почему бы этим не воспользоваться?
Повышать приоритет обработчика - не очень хороший вариант, поскольку обработка может быть ресурсоемкой и из-за нее самой и возникнет дефицит процессорного времени.
Go to the top of the page
 
+Quote Post
PanovAU
сообщение Apr 10 2013, 10:00
Сообщение #5





Группа: Новичок
Сообщений: 9
Регистрация: 12-01-05
Из: Екатеринбург
Пользователь №: 1 905



Цитата(Boriska @ Apr 8 2013, 03:53) *
Если буфер полностью заполнен, то отправитель, при отправке очередного пакета, не получит подтверждение, что его сообщение доставлено.

По моему, здесь вы ошибаетесь. Во первых, обычно на CAN сидят несколько узлов. И если один не выдал ACK по какой либо причине и не выдал флага ошибки, то это совсем не означает что ACK не выдаст другой узел. Во вторых, в Reference manual я не смог найти, что при переполнении FIFO флаг ACK не выставляется. Есть два режима, когда в конце очереди всегда самое новое сообщение (затирает предыдущее), либо очередь блокируется и новые сообщения в нее не попадают.

Цитата
Overrun
Once the FIFO is in pending_3 state (i.e. the three mailboxes are full) the next valid
message reception will lead to an overrun and a message will be lost. The hardware
signals the overrun condition by setting the FOVR bit in the CAN_RFR register. Which
message is lost depends on the configuration of the FIFO:
● If the FIFO lock function is disabled (RFLM bit in the CAN_MCR register cleared) the
last message stored in the FIFO will be overwritten by the new incoming message. In
this case the latest messages will be always available to the application.
● If the FIFO lock function is enabled (RFLM bit in the CAN_MCR register set) the most
recent message will be discarded and the software will have the three oldest messages
in the FIFO available.


Поправьте, если не прав.
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 23rd July 2025 - 20:32
Рейтинг@Mail.ru


Страница сгенерированна за 0.01387 секунд с 7
ELECTRONIX ©2004-2016