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

 
 
 
Reply to this topicStart new topic
> Проблема с UART, принимает только несколько байт из пакета
M0HAX
сообщение Oct 4 2011, 13:24
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 33
Регистрация: 22-09-08
Пользователь №: 40 378



Привет всем!
Столкнулся со следующей проблемой взаимодействия UARTа с FreeRTOS:
Внешнее устройство общается с платой под управлением FreeRTOS через шину 1Мбит через порты RXD2 и ТXD2.
Отправку данных в устройство осуществляю просто записью
Код
  U2THR = что-то;
   while (!(U2LSR_bit.TEMT));


а данные принимаю через USART2 RBR Interrupt. Это прерывание объявил как __fiq со всеми вытекающими последствиями.
Внутри этого прерывания не использую функции FreeRTOS, поэтому само прерывание не окаймляю макросами сохранения и восстановления контекста. Оно как бы должно работать вне системы.
Помимо этого, внутри ядра не использую функции типа __disable_interrupt() и __enable_interrupt(), т.к. они затрагивают fiq-прерывания, а вместо них использую __disable_irq() и __enable_irq().
Кроме этого, первой строкой при вызове irq-прерывания использую MSR CPSR_c, #146 - разрешение fiq-прерывания
Код
irq_handler:
        MSR     CPSR_c, #146
        portSAVE_CONTEXT    ;; Save the context of the current task...
        
        MVN      R0,#+255
        LDR      R0,[R0, #+0]                 ;; забираем адрес процедуры текущего активного прерываниЯ
        MOVS     R5,R0
        MOVS     R4,R5
        CMP      R4,#+0                        ;; адрес ненулевой -> переход на обработчик
        BEQ      ??irq_handler_0             ;; либо сброс прерываниЯ и выход
        MOV      LR,PC
        BX       R4                                 ;; переход на обработчик соответствующего IRQ-прерываниЯ
        B        ??irq_handler_1
??irq_handler_0:
        MVN      R0,#+255
        MOV      R1,#+0
        STR      R1,[R0, #+0]                  ;; сброс флага прерываниЯ - VICAddress = 0
??irq_handler_1:

        portRESTORE_CONTEXT        ;; Restore the context of the selected task.


Как только соберу кадр с помощью прерывания по приему UART2, то делаю внутри него же T2TCR_bit.CE = 1, чтобы вызвать прерывание от таймера(irq-прерывание), который должен уже проверить
кадр на контрольную сумму и послать FreeRTOS-сообщение задаче, которая инициировала связь со внешним устройством и ждет прихода кадра от него:
Код
  SendAddressToBus(THREBuffer[0]);                                                                                      // выставляем на шину признак адреса  
  xResult = xQueueReceive(xFlagCadrBUSQueue, &ucState, 1000);                                            // ждем кадра данных
  if (xResult != pdPASS) xResult = _TIMEOUT_ERROR; else xResult = ucState;

Так вот, после посылки адреса и признака чтения данных, внешнее устройство должно вернуть кадр данных. Но он приходит не полностью, ибо больше прерывания по приему не возникают...
Если я вместо строки
Код
xResult = xQueueReceive(xFlagCadrBUSQueue, &ucState, 1000);                                            // ждем кадра данных

вставлю while(1); и просто подожду чуть и остановлю эмулятор,то вижу,что данные пришли ВСЕ и так получается всегда.
Т.е. здесь в некачественном приеме как-то замешан FreeRTOS,но ведь я везде разрешил fiq-прерывания - что ему бы не вызваться и не принять данные.....
В чем трабл не могу понять,блин... Где косяк, об котрый надо стукнуться? Может кто подскажет?

Вот таблица векторов
Код
__vector:
        LDR   PC, [PC, #+24]               ;; Reset. Выбираем из памЯти адрес перехода
        LDR   PC, [PC, #+24]               ;; Undefined instructions
        B     vPortYieldProcessor          ;; переход на обработчик SWI(программное прерывание)
        LDR   PC, [PC, #+24]               ;; Prefetch abort
        LDR   PC, [PC, #+24]               ;; Data abort

__vector_0x14
        DC32  0                            ;; RESERVED
        LDR   PC, [PC, #+24]               ;; IRQ
        LDR   PC, [PC, #+24]               ;; FIQ

;;----------------------------------------------------------------------------------------
;; таблица адресов переходов
;;----------------------------------------------------------------------------------------
        DC32  __iar_program_start          ;; Reset
        DC32  undef_handler                ;; Undefined instructions
        DC32  0                            ;; Software interrupt (SWI/SVC)
        DC32  prefetch_handler             ;; Prefetch abort
        DC32  data_handler                 ;; Data abort
        DC32  0                            ;; RESERVED
        DC32  irq_handler                ;; IRQ
        DC32  vBUS_fiq_handler                  ;; FIQ


Вот само fiq-прерывание. За код не пинайте,ибо уже на скорую руку делал всякие извращенные изменения,не заботясь о красоте и т.п.
Код
__fiq __arm void vBUS_fiq_handler(void){
unsigned portCHAR   ucData, ucStatus, temp;

  temp = 0;
  ucStatus = U2IIR_bit.IID;
  switch (ucStatus){
   case  _CTI:
   case  _RDA:
  lll1:
           ucData = U2RBR;                    
           temp = 1;
           if ((U2LCR_bit.PS == _FORCED_1) || bAddressReceiveFlag){
            
             if (U2LCR_bit.PS == _FORCED_1){
               bAddressSendFlag = true;
               U2LCR_bit.PS = _FORCED_0;
             } else  
               bAddressReceiveFlag = false;
            
             ucCnt_RBR = 1;
             RBRBuffer[0] = ucData;
             if (U2LSR & 0x01) goto lll1;
             break;
           };  
          
           RBRBuffer[ucCnt_RBR++] = ucData;
          
           if (ucCnt_RBR == 2) ucLEN_RBR = ucData;
           if (ucCnt_RBR == (ucLEN_RBR + 3)) T2TCR_bit.CE = 1;
          
           if (U2LSR & 0x01) goto lll1;
           break;          
  };

  VICADDRESS = 0;
}


Трабл не зависит,использую ли я FIFO или нет. От него зависит только,сколько я байт получу... но не весь пакет в 64 байта - максимум приходят только первые 16 байт, а потом молчок...
Go to the top of the page
 
+Quote Post
M0HAX
сообщение Oct 6 2011, 13:28
Сообщение #2


Участник
*

Группа: Участник
Сообщений: 33
Регистрация: 22-09-08
Пользователь №: 40 378



Сделал другой проект, выкинул все лишнее, оставил только FreeRTOS и задачу и прерывания работы с UART2, через которое осуществляется связь со внешним устройством. Все упростил - результат тот же печальный. Через другой UART вывел на комп полученные данные и запустил программу на плате без эмулятора. В терминале вижу, что данные от внешнего устройства на плату с 2378 приходят все и всё. А ту же саму программу запускаю через эмулятор, то не работает прием данных от внешнего устройства - перестают возникать fiq-прерывания по приему от UART2 после того,как в программе вызовется обработчик SWI(программное прерывание), в котором происходит ручное переключение задач(например, это прерывание вызвается внутри xQueueReceive()). Причем проверял, нигде fiq-прерывания не запрещаются. Может эмулятор что-то не успевает сработать или теряет прерывания? Эмулятор IAR J-Link-ARM
Go to the top of the page
 
+Quote Post
kan35
сообщение Oct 7 2011, 04:28
Сообщение #3


Знающий
****

Группа: Участник
Сообщений: 537
Регистрация: 22-02-06
Пользователь №: 14 594



Честно сказать не все ясно по коду, но:
Я бы для начала избавился от операторов goto в fiq.
Во вторых - не ясно, зачем вообще fiq? usart - медленное устройство, используйте irq. И соответственно там собирайте кадр и оттуда отправляйте в queue.

еще, в конструкциях типа:
Код
          
switch
......
        if ((U2LCR_bit.PS == _FORCED_1) || bAddressReceiveFlag){
             ...
             break;
           };

break -точно ли выходит из case а не из if?
}; - лучше без ;

PS: если количество байт всегда известно, то лучше dma использовать.
Go to the top of the page
 
+Quote Post
M0HAX
сообщение Oct 10 2011, 06:21
Сообщение #4


Участник
*

Группа: Участник
Сообщений: 33
Регистрация: 22-09-08
Пользователь №: 40 378



Цитата(kan35 @ Oct 7 2011, 08:28) *
Честно сказать не все ясно по коду, но:
Я бы для начала избавился от операторов goto в fiq.

Я ж написал, что
Цитата
. За код не пинайте,ибо уже на скорую руку делал всякие извращенные изменения, не заботясь о красоте и т.п.
Да и зря на goto так наезжаете, ибо он часто помогает избавиться от излишнего кода и не нарушает логики в данном случае.

Цитата(kan35 @ Oct 7 2011, 08:28) *
Во вторых - не ясно, зачем вообще fiq? usart - медленное устройство, используйте irq. И соответственно там собирайте кадр и оттуда отправляйте в queue.

Все irq-прерывания проходят через сохранение и восстановление контекста. Зачем мне нужны эти лишние операции, когда непонятно было успевает ли принять данные или нет система, да еще использовать внутри этого прерывания всякие функции freertos-а, да еще в конце прерывания контекст переключать из-за queue? На 1Мб usart получается не совсем медленным, однако.

Цитата(kan35 @ Oct 7 2011, 08:28) *
еще, в конструкциях типа:
Код
          
switch
......
        if ((U2LCR_bit.PS == _FORCED_1) || bAddressReceiveFlag){
             ...
             break;
           };

break -точно ли выходит из case а не из if?
}; - лучше без ;

PS: если количество байт всегда известно, то лучше dma использовать.

"break" выходит из case,однако.
";" - ну вот мне так нравится )
количество байт кадра известно становится только при приходе кадра. Да и не до dma было, ибо зачем новый геморой, когда dma еще не пользовался и не знаю, какие там косяки могут быть. Сначала так должно было заработать.
Все это,конечно,лирика, но без эмулятора работает все четко..
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 1st July 2025 - 01:53
Рейтинг@Mail.ru


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