Перейти к содержанию
    

LPC2388 CAN freeRTOS

Плата с lpc2388 под управленим freeRTOS. Получаю сообщение по CAN1 - вваливаюсь в обработчик прерывания. Если дальше выполнять пошагово в дебаггере (jtag) то всё хорошо работает, но если запустить (RUN), то раз в ~10 сообщений вываливается в Pabt. Причём вываливается после выхода из обработчика прерывания. В R14(LR) при этом чаще всего 0x286e9b12.

Поскольку прерывание может пробуждать другие task'и, то оформлял как оформлено прерывание от UART след. образом:

 

vCAN_ISREntry

 

portSAVE_CONTEXT ; Save the context of the current task.

 

LDR R0, =vCAN_ISR ; Call the ISR routine.

MOV LR, PC

BX R0

 

portRESTORE_CONTEXT ; Restore the context of the current task -

; which may be different to the task that

; was interrupted.

 

 

 

Далее текст главной функции прерывания:

 

void vCAN_ISR(void) //__irq

{

portBASE_TYPE xHigherPriorityTaskWoken;

CANStatus = CAN_RX_SR;

if ( CANStatus & (1 << 8) )

{

CAN1RxCount++;

xHigherPriorityTaskWoken = CAN_ISR_Rx1();

}

 

if ( CAN1GSR & (1 << 6 ) )

{

/* The error count includes both TX and RX */

CAN1ErrCount = (CAN1GSR >> 16 );

}

 

VICVectAddr = 0; /* Acknowledge Interrupt */

 

/* Actual macro used here is port specific. */

portEXIT_SWITCHING_ISR(xHigherPriorityTaskWoken);

}

 

И подпрограмма обработки приёма по CAN

 

portBASE_TYPE CAN_ISR_Rx1( void )

{

portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;

 

xCANMsg * pMsg = ( xCANMsg * ) pvPortMalloc( sizeof( xCANMsg ) );

 

if(pMsg == 0){

vSerialPutString( NULL, "No memory avalible", 25);

xSerialPutChar( NULL, CR, comNO_BLOCK);

while(1){};

}

pMsg->Frame = CAN1RFS;

pMsg->MsgID = CAN1RID; // ID //change by gongjun

pMsg->DataA = CAN1RDA; // Data A

pMsg->DataB = CAN1RDB; // Data B

 

xQueueSendToBackFromISR( receiveCANQueue, ( void * ) &pMsg, &xHigherPriorityTaskWoken);

 

CAN1RxDone = TRUE;

CAN1CMR = 0x04; // release receive buffer

return xHigherPriorityTaskWoken;

}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В R14(LR) при этом чаще всего 0x286e9b12.

Это для какого режима проца смотрели?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Это для какого режима проца смотрели?

 

Для abort

Сменил настройки MAM с disabled на fully enabled - сообщений стало гораздо больше проходить перед Pabt.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для abort

Сменил настройки MAM с disabled на fully enabled - сообщений стало гораздо больше проходить перед Pabt.

Может здесь ответ есть?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Может здесь ответ есть?

В приведенном коде своих проблем для начала выше головы.

1.Всякой мути надергано и сляпано из каких-то исходников :(

2.Выделение динамической памяти в обработчике прерывания без всякой надобности да еще и не освобождается при этом.

3.Для копирования в очередь передается не указатель на CAN буфер а указатель на этот указатель..

4.Вызов каой-то мутной печати из обработчика..

5......

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В приведенном коде своих проблем для начала выше головы.

1.Всякой мути надергано и сляпано из каких-то исходников :(

2.Выделение динамической памяти в обработчике прерывания без всякой надобности да еще и не освобождается при этом.

3.Для копирования в очередь передается не указатель на CAN буфер а указатель на этот указатель..

4.Вызов каой-то мутной печати из обработчика..

5......

 

извините, возможно я не совсем (или совсем не) разбираюсь в теме, но у меня есть следующие возражения:

пункт3:

поскольку объекты сообщения типа xCANMsg занимают в памяти 16 байт, то накладно было бы их копировать по значению (а в очереди freeRTOS данные по значению и копируются - Items are queued by copy not reference), следовательно я храню в очереди указатель.

Объявление очереди:

receiveCANQueue = xQueueCreate( 40, sizeof( struct xCANMsg * ) );//содержит указатели на xCANMsg

В

а указатель на этот указатель

Из описания API работы с очередями с freeRTOS.org:

portBASE_TYPE xQueueSendToBackFromISR(

xQueueHandle pxQueue,

const void *pvItemToQueue,

portBASE_TYPE *pxHigherPriorityTaskWoken

);

где pvItemToQueue - A pointer to the item that is to be placed on the queue. The size of the items the queue will hold was defined when the queue was created, so this many bytes will be copied from pvItemToQueue into the queue storage area.

Следовательно, если я хочу поместить указатель на xCANMsg в очередь, я должен передать указатель на него, т.е. указатель на указатель.

 

пункт2: Я не знаю как можно по-другому организовать приём сообщений от CAN и постановку их в очередь. Если "просто" обьявить переменную типа xCANMsg и передать указатель на неё в очередь, то следующее принятое сообщение затрёт предыдущее, поскольку будет записываться на то же место. Или может быть я заблуждаюсь?

Насчёт освобождения памяти - я его освобождаю в том task'е, где я обрабатываю это сообщение:

 

if( xQueueReceive( receiveCANQueue, &( pRecMsg ), ( portTickType ) 1 ) )

{

//mirror message

pMsg->Frame = pRecMsg->Frame; // 29-bit, no RTR, DLC is 8 bytes

pMsg->MsgID = pRecMsg->MsgID; // CAN ID

pMsg->DataA = pRecMsg->DataA;

pMsg->DataB = pRecMsg->DataB;

//free memory pRecMsg

vPortFree(pRecMsg) ;

CAN1_SendMessage( pMsg ) ;

}

 

пункт4: вполне согласен. Вопрос: как печатать сообщения: оформлять отдельный task с очередью, в которую передавать указатели на строки, которые нужно распечатать и из task'a их печатать?

 

Буду рад любым замечаниям.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Буду рад любым замечаниям.

Тем не менее копировать 16 байт в очередь наименьшее из зол. При желании потом можете сделать отдельный кольцевой буфер кратный 16 байтам, принимать в него и посылать указатели на него. Можно и слегка доработать FreeRTOS добавив вариант с возвращением указателя на место в буфере вместо копирования в буфер....По печати - печать через отдельный буфер для печати разгружаемый из обработчика прерывания UART.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

спасибо за замечания

Ближе к теме.

1. Может ли Pabt возникать из-за программной ошибки и в каких случаях. Если нет, то как с ним бороться.

2. В erratasheet'e меликом в описании Flash.1 problem упоминается :Do not use even values for CCLKSEL

А ранее они в этом же документе писали: PLL.1: Problem: The maximum output of the CCO within the PLL block is limited to 290 MHz.

Т.е. FCCO 275 - 290 MHz

А при кварце 14,7456 МГц и наличии USB (48МГц) подобрать подходящие M и N с небольшой погрешностью (менее 1000 ppm) неполучается. Так что, теперь квац нужно менять?!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Проблема решилась след. образом: убрал из прерывания динамическое выделение памяти и стал копировать сообщения по значению в очередь (очередь пришлось урезать до 4-5 значений).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

очередь пришлось урезать до 4-5 значений.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...