M0HAX 0 4 октября, 2011 Опубликовано 4 октября, 2011 · Жалоба Привет всем! Столкнулся со следующей проблемой взаимодействия 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 байт, а потом молчок... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
M0HAX 0 6 октября, 2011 Опубликовано 6 октября, 2011 · Жалоба Сделал другой проект, выкинул все лишнее, оставил только FreeRTOS и задачу и прерывания работы с UART2, через которое осуществляется связь со внешним устройством. Все упростил - результат тот же печальный. Через другой UART вывел на комп полученные данные и запустил программу на плате без эмулятора. В терминале вижу, что данные от внешнего устройства на плату с 2378 приходят все и всё. А ту же саму программу запускаю через эмулятор, то не работает прием данных от внешнего устройства - перестают возникать fiq-прерывания по приему от UART2 после того,как в программе вызовется обработчик SWI(программное прерывание), в котором происходит ручное переключение задач(например, это прерывание вызвается внутри xQueueReceive()). Причем проверял, нигде fiq-прерывания не запрещаются. Может эмулятор что-то не успевает сработать или теряет прерывания? Эмулятор IAR J-Link-ARM Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kan35 7 7 октября, 2011 Опубликовано 7 октября, 2011 · Жалоба Честно сказать не все ясно по коду, но: Я бы для начала избавился от операторов goto в fiq. Во вторых - не ясно, зачем вообще fiq? usart - медленное устройство, используйте irq. И соответственно там собирайте кадр и оттуда отправляйте в queue. еще, в конструкциях типа: switch ...... if ((U2LCR_bit.PS == _FORCED_1) || bAddressReceiveFlag){ ... break; }; break -точно ли выходит из case а не из if? }; - лучше без ; PS: если количество байт всегда известно, то лучше dma использовать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
M0HAX 0 10 октября, 2011 Опубликовано 10 октября, 2011 · Жалоба Честно сказать не все ясно по коду, но: Я бы для начала избавился от операторов goto в fiq. Я ж написал, что . За код не пинайте,ибо уже на скорую руку делал всякие извращенные изменения, не заботясь о красоте и т.п. Да и зря на goto так наезжаете, ибо он часто помогает избавиться от излишнего кода и не нарушает логики в данном случае. Во вторых - не ясно, зачем вообще fiq? usart - медленное устройство, используйте irq. И соответственно там собирайте кадр и оттуда отправляйте в queue. Все irq-прерывания проходят через сохранение и восстановление контекста. Зачем мне нужны эти лишние операции, когда непонятно было успевает ли принять данные или нет система, да еще использовать внутри этого прерывания всякие функции freertos-а, да еще в конце прерывания контекст переключать из-за queue? На 1Мб usart получается не совсем медленным, однако. еще, в конструкциях типа: switch ...... if ((U2LCR_bit.PS == _FORCED_1) || bAddressReceiveFlag){ ... break; }; break -точно ли выходит из case а не из if? }; - лучше без ; PS: если количество байт всегда известно, то лучше dma использовать. "break" выходит из case,однако. ";" - ну вот мне так нравится ) количество байт кадра известно становится только при приходе кадра. Да и не до dma было, ибо зачем новый геморой, когда dma еще не пользовался и не знаю, какие там косяки могут быть. Сначала так должно было заработать. Все это,конечно,лирика, но без эмулятора работает все четко.. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться