|
CAN на STM32F + FreeRTOS |
|
|
|
Apr 2 2013, 09:05
|
Участник

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

|
Пытаюсь обрабатывать входящие сообщения по шине CAN. Хотелось бы чтобы полученные сообщения были гарантированно обработаны, а если ресурсов не хватает, то чтобы они и не были получены.
Если в обработке прерывания просто очистить флаг прерывания и установить семафор, а чтение и очистку почтового ящика (CAN) сделать в отдельной задаче, то ничего не работает. После выхода из прерывания без установки RFOM (очистка ящика), прерывание тут же вызывается снова и задача по чтению сообщения вообще не получает управления.
А если в обработчике очистить флаг прерывания, прочитать и очистить почтовый ящик, то задача обработки получит управления, но тут может возникнуть ситуация, когда сообщение получено, прочитано, но не обработано, поскольку задаче по обработке не хватило ресурсов. Как можно решить такую задачу?
|
|
|
|
|
 |
Ответов
(1 - 4)
|
Apr 2 2013, 16:42
|
Участник

Группа: Участник
Сообщений: 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 ); }
} }
|
|
|
|
|
Apr 7 2013, 21:53
|
Участник

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

|
Цитата(zebrox @ Apr 5 2013, 20:05)  У обработчика должен быть буфер входящих сообщений. Приемник в него записывает, если при записи нового сообщения буфер заполняется до определенного уровня, то это можно использовать как сигнал для увеличения приоритета обработчика, например, или генерацию аларма делать. В реализации CAN на STM32 уже есть буфер на 3 входящих сообщения (т.н. почтовые ящики). Почему бы ими не воспользоваться? Если буфер полностью заполнен, то отправитель, при отправке очередного пакета, не получит подтверждение, что его сообщение доставлено. Это очень удобно. Почему бы этим не воспользоваться? Повышать приоритет обработчика - не очень хороший вариант, поскольку обработка может быть ресурсоемкой и из-за нее самой и возникнет дефицит процессорного времени.
|
|
|
|
|
Apr 10 2013, 10:00
|
Группа: Новичок
Сообщений: 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. Поправьте, если не прав.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|