Jump to content

    

Неполадки с очередью в USART

Есть еще вот такой код в нескольких местах port.c

ldr     r3, pxCurrentTCBConst

Который ломается при сборке с LTO, или не ломается, как повезет.

https://bugs.launchpad.net/gcc-arm-embedded/+bug/1763050

Edited by amaora

Share this post


Link to post
Share on other sites

На M4F с АРМ компилятором 6-версии нечего не ломается с включенным LTO. По правде абсолютно не вижу смысла в LTO, размер кода уменьшается на сущие копейки, а в скорости и вовсе нет прибавки.

Share this post


Link to post
Share on other sites

Добрался до отладки, оказывается другие задачи при этом продолжают выполняться. Но прерывание USART больше не происходит. Настройки его не изменились, все как задавал.

(gdb) p/x *((USART_TypeDef *) (0x40000000 + 0x4800))
$20 = {SR = 0xc0, RESERVED0 = 0x0, DR = 0x10d, RESERVED1 = 0x0, BRR = 0x2d9, RESERVED2 = 0x0, CR1 = 0x34ac, RESERVED3 = 0x0, CR2 = 0x0, RESERVED4 = 0x0, CR3 = 0x0,
  RESERVED5 = 0x0, GTPR = 0x0, RESERVED6 = 0x0}

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

0x20001548 <ucHeap+4256>:       0xa5a5a5a5      0xa5a5a5a5      0xa5a5a5a5      0xa5a5a5a5
0x20001558 <ucHeap+4272>:       0xa5a5a5a5      0xa5a5a5a5      0xa5a5a5a5      0xa5a5a5a5
0x20001568 <ucHeap+4288>:       0xa5a5a5a5      0xa5a5a5a5      0xa5a5a5a5      0xa5a5a5a5
0x20001578 <ucHeap+4304>:       0xa5a5a5a5      0xa5a5a5a5      0xa5a5a5a5      0xa5a5a5a5
0x20001588 <ucHeap+4320>:       0xa5a5a5a5      0xa5a5a5a5      0xa5a5a5a5      0xa5a5a5a5
0x20001598 <ucHeap+4336>:       0xa5a5a5a5      0xa5a5a5a5      0xa5a5a5a5      0xa5a5a5a5
0x200015a8 <ucHeap+4352>:       0xa5a5a5a5      0x20000a00      0x20000000      0x200016af
0x200015b8 <ucHeap+4368>:       0xe000ed04      0x00000000      0x20000a10      0x000067b8
0x200015c8 <ucHeap+4384>:       0x00000000      0xffffffed      0xc04fbb9e      0x4f000000
0x200015d8 <ucHeap+4400>:       0x3851b716      0x3a03126e      0x3ba3d70a      0x20000a00
0x200015e8 <ucHeap+4416>:       0x20000000      0x200016e7      0xe000ed04      0x00000000
0x200015f8 <ucHeap+4432>:       0x20000a10      0x0000693b      0x00000000      0xffffffed
0x20001608 <ucHeap+4448>:       0xc04fbb9e      0x4f000000      0x3851b716      0x3a03126e
0x20001618 <ucHeap+4464>:       0x3ba3d70a      0x3d4ccccd      0x36a7c5ab      0x799a130c
0x20001628 <ucHeap+4480>:       0x41c73406      0x00000000      0x00000000      0x00000000
0x20001638 <ucHeap+4496>:       0x00000000      0x00000000      0x00000000      0x00000000
0x20001648 <ucHeap+4512>:       0x00000000      0x00000000      0xffffffff      0x00000001
0x20001658 <ucHeap+4528>:       0x00000028      0x00000028      0x08003dc8      0x21000000
0x20001668 <ucHeap+4544>:       0x3c72fa4f      0x00000000      0x00000000      0x3c72fa4f
0x20001678 <ucHeap+4560>:       0x3f800000      0x3f800000      0x00000000      0x00000000
0x20001688 <ucHeap+4576>:       0x00000000      0x3e2be000      0x3e652aab      0x415182e6
0x20001698 <ucHeap+4592>:       0x4e6e6b28      0x00000001      0x00000000      0x3effffff
0x200016a8 <ucHeap+4608>:       0x80000012      0x08003f2d      0x00000000      0xffffffff
0x200016b8 <ucHeap+4624>:       0x00000000      0x0800dd89      0x0800dd8a      0x20000380
0x200016c8 <ucHeap+4640>:       0x20001770      0x00000005      0x0800c214      0x20000380
0x200016d8 <ucHeap+4656>:       0xa5a5a5a5      0x0800402b      0x3c72fa4f      0x70000000
0x200016e8 <ucHeap+4672>:       0x00000000      0x080018f3      0x3f800000      0x3f800000
0x200016f8 <ucHeap+4688>:       0x00000000      0x00000000      0x00000001      0x00343131
0x20001708 <ucHeap+4704>:       0xc04fbb9e      0x4079cf46      0x3d24c763      0xbf54132b
0x20001718 <ucHeap+4720>:       0x3e11c9af      0xbc3e95f2      0x799a130c      0x799a130c
0x20001728 <ucHeap+4736>:       0x0800d35c      0x00000156      0x0800c8ac      0x2000002c
0x20001738 <ucHeap+4752>:       0x0800dbfc      0x0800dcd6      0x20000380      0x080065b9
0x20001748 <ucHeap+4768>:       0x0800dcd6      0x2000175c      0xa5a5a5a5      0x08006d6d
0x20001758 <ucHeap+4784>:       0x0800dd7c      0x00000020      0x00000052      0x00000020
0x20001768 <ucHeap+4800>:       0x00000072      0x0800c214      0x2000002f      0x00000000
0x20001778 <ucHeap+4816>:       0x2000002f      0x00000000      0x0800d35c      0x08007059
0x20001788 <ucHeap+4832>:       0x0800dcd5      0x20000380      0x20000000      0x00000000
0x20001798 <ucHeap+4848>:       0x00000000      0x2000002c      0x0800dbfc      0x080027d9
0x200017a8 <ucHeap+4864>:       0xa5a5a5a5      0x08003aed      0xa5a5a5a5      0xa5a5a5a5
(gdb) info symbol 0x08003f2d
xQueueGenericSend.constprop.95 + 461 in section .text

Проблема видимо в том, что перестало происходить прерывание и никто не забирает данные из очереди. :unknw:

В NVIC тоже бы включено все.

(gdb) p/x *((NVIC_Type*)(0xE000E000UL+0x0100UL))
$23 = {ISER = {0x40000, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, RESERVED0 = {0x0 <repeats 24 times>}, ICER = {0x40000, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, RSERVED1 = {
    0x0 <repeats 24 times>}, ISPR = {0x40000, 0x80, 0x20000, 0x0, 0x0, 0x0, 0x0, 0x0}, RESERVED2 = {0x0 <repeats 24 times>}, ICPR = {0x40000, 0x80, 0x20000, 0x0, 0x0, 0x0,
    0x0, 0x0}, RESERVED3 = {0x0 <repeats 24 times>}, IABR = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, RESERVED4 = {0x0 <repeats 56 times>}, IP = {0x0 <repeats 39 times>,
    0xb0, 0x0 <repeats 200 times>}, RESERVED5 = {0x0 <repeats 516 times>, 0x410fc241, 0x14c22000, 0x8000000, 0xfa050300, 0x0, 0x200, 0x0, 0x0, 0xf0f00000, 0x0, 0x0, 0x0,
    0x0, 0xe000edf8, 0xe000edf8, 0x0, 0x30, 0x200, 0x100000, 0x0, 0x100030, 0x0, 0x1000000, 0x0, 0x1101110, 0x2112000, 0x21232231, 0x1111131, 0x1310132, 0x0, 0x0, 0x0,
    0x0, 0x0, 0xf00000, 0x0, 0x800, 0x0 <repeats 23 times>, 0x30003, 0x0, 0x0, 0x1000401, 0x0 <repeats 64 times>}, STIR = 0x0}
void USART_startup()
{
    /* Enable USART3 clock.
     * */
    RCC->APB1ENR |= RCC_APB1ENR_USART3EN;

    /* Enable USART3 pins.
     * */
    GPIO_set_mode_FUNCTION(GPIO_USART3_TX);
    GPIO_set_mode_FUNCTION(GPIO_USART3_RX);

    /* Alloc queues.
     * */
    hal_USART.xRX = xQueueCreate(20, sizeof(char));
    hal_USART.xTX = xQueueCreate(40, sizeof(char));

    /* Configure USART.
     * */
    USART3->BRR = CLOCK_APB1_HZ / hal.USART_baud_rate;
    USART3->CR1 = USART_CR1_UE | USART_CR1_M | USART_CR1_PCE
        | USART_CR1_RXNEIE | USART_CR1_TE | USART_CR1_RE;
    USART3->CR2 = 0;
    USART3->CR3 = 0;

    /* Enable IRQ.
     * */
    NVIC_SetPriority(USART3_IRQn, 11);
    NVIC_EnableIRQ(USART3_IRQn);
}

 

Share this post


Link to post
Share on other sites
39 минут назад, amaora сказал:

Проблема видимо в том, что перестало происходить прерывание и никто не забирает данные из очереди.

1. А физически прерывание на прием работает? В "зависшем" состоянии отправлять символы с консоли и поставить точку останова в прерывании (или как там у Вас безопасно проверить), на RXNE реагирует?

2. В программе есть места с возможными взаимными блокировками потоков?

Share this post


Link to post
Share on other sites
44 minutes ago, Arlleex said:

А физически прерывание на прием работает? В "зависшем" состоянии отправлять символы с консоли и поставить точку останова в прерывании (или как там у Вас безопасно проверить), на RXNE реагирует?

Отравлять и принимать байты можно читая регистры USART из gdb, он работает. Посмотрел еще, другие задачи все таки не работают. Только одна задача выполняется, другим управление не передается. Прерывание PendSV не происходит. Переменная uxCriticalNesting равна 1 вне функций ОС. Видимо и в BASEPRI не ноль, но не знаю как его посмотреть из gdb.

То есть кто-то сделал taskENTER_CRITICAL но не сделал EXIT? Это должна быть та задача которая осталась выполняться? Она только vTaskDelayUntil вызывает.

Upd: Даже удалось "разлочить" зависание через gdb. Путем сброса переменной uxCriticalNesting в 0, и записи флага в USART3->CR1. :pardon:

Edited by amaora

Share this post


Link to post
Share on other sites
23 minutes ago, amaora said:

утем сброса переменной uxCriticalNesting

Так вы, похоже, что-то с критическими секциями не то сделали)

Share this post


Link to post
Share on other sites

Вот это самое сложное, что делается. В имеющейся конфигурации эта функция вызывается только из одной задачи, что не должно вызвать проблем. С критическими секциями ничего не делаю у себя.
 

float ADC_get_VALUE(int xGPIO)
{
    float            fADC = 0.f;
    int            xCH;

    if (xSemaphoreTake(hal_ADC.xSem, (TickType_t) 10) == pdTRUE) {

        xCH = (xGPIO == GPIO_ADC_INTERNAL_TEMP) ? 16
            : XGPIO_GET_CH(xGPIO);

        ADC1->SQR3 = xCH;
        ADC1->CR2 |= ADC_CR2_SWSTART;

        while ((ADC1->SR & ADC_SR_EOC) == 0) {

            taskYIELD();
        }

        ADC1->SR &= ~ADC_SR_EOC;
        fADC = (float) ADC1->DR;

        fADC = (xCH != 16) ? fADC * hal.ADC_const.GS
            : hal.ADC_const.TEMP[1] * fADC + hal.ADC_const.TEMP[0];

        xSemaphoreGive(hal_ADC.xSem);
    }

    return fADC;
}

 

Share this post


Link to post
Share on other sites
2 minutes ago, amaora said:

С критическими секциями ничего не делаю у себя.

Странно! Эта переменная инкрементируется в функции 

vPortEnterCritical

которая, в свою очередь, вызывается всякий раз, когда нам нужна критическая секция. Попробуйте выяснить, кто её вызывает.

Share this post


Link to post
Share on other sites
1 minute ago, haker_fox said:

Странно! Эта переменная инкрементируется в функции 


vPortEnterCritical

которая, в свою очередь, вызывается всякий раз, когда нам нужна критическая секция. Попробуйте выяснить, кто её вызывает.

Ее почти каждая функция FreeRTOS внутри себя вызывает.

Share this post


Link to post
Share on other sites

Рекомендую прикрутить Percepio Tracealyzer и посмотреть все что происходит с ОСью, в частности будет видно кто что вызывает. Где-то на форуме проскакивала "не жадная" версия.

 

И попробуйте функцию отправки изменить на:

void USART_putc(int c)
{
    char        xC = (char) c;

    GPIO_set_HIGH(GPIO_LED);

    xQueueSendToBack(hal_USART.xTX, &xC, pdMS_TO_TICKS(1));

    USART3->CR1 |= USART_CR1_TXEIE;

    GPIO_set_LOW(GPIO_LED);
}

 

Edited by Neo_Matrix

Share this post


Link to post
Share on other sites
void irq_USART3()
{
...
    if (SR & USART_SR_TXE) {

Надо смотреть, что прерывание разрешено по TXE

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now