Pull to refresh
7
46.5
Данил@danil_12345

User

Send message

Если п.1<>п.3

Что значит оператор "<>" ?

После 72ой минуты 32 таймер переполнится и начнет считать заново. Можно генерировать прерывания и по slave таймеру, умножать счетчик прерываний на 0xFFFFFFFF и прибавлять cnt32. В результате получится уже тайм штамп типа uint64_t.

А что будет, если при чтении попадëм на обновление слейв-таймера?

Я видел такое решение

uint32_t time_stamp_get_us( void ) {
    uint32_t tim_word_lo = 0x0000; 
    uint32_t tim_word_hi = 0x0000;
    do {
        tim_word_lo = TIM3->CNT;
        tim_word_hi = TIM9->CNT;
    } while( tim_word_hi != TIM9->CNT );
    uint32_t timestamp_dword=(tim_word_hi<<16)|tim_word_lo;
    return timestamp_dword;
}

Однако почему так сделано - затрудняюсь пояснить.

Да. Это классическая "ошибка 71ой минуты".

>>> ((10**(-6))*(2**32))/60
71.58278826666667

Что делать - не знаю.
Переходить на RISC-V.
Там 64битный systick встроен прямо в ядро!

Обновление tim_word_hi происходит раз в 65 ms.
Я бы предпочел ничего не делать.
На следующей итерации прочитается уже корректное значение.

А я предлагаю каскадный 32бит таймер, который вообще прерывания не производит.

в обработчике прерываний по переполнению тех же 16 битных таймеров? А зависимый функционал будет плясать от значения такого счетчика.

Прерывания каждую микросекунду?
Приложение будет тормозить.

A RTT будет работать при пере сбросе питания?
Вот UART сохраняет Link, если Target ресутнуть.

Никогда не ждите событий в бесконечных циклах - в них и поляжете.

У меня как раз есть условие выхода

            uint32_t up_time = TIME_GetMs();
            uint32_t diff = up_time - up_time_start;
            if(200 < diff) {
                res = false;
                break;
            }

Спасибо за описание решения. Но чем кольцевой буфер отличается от FIFO?

Надо ждать в for(;;) пока UART трансивер под освободит TxFIFO и вложить туда новые данные.
Или просто увеличивать счетчик об ошибках.

Хороший вопрос. Пока у нас разрешена только SafeRTOS

Можно ждать отправки не всегда, а только в случае, если в программном буфере TxFIFO не достаточно места, чтобы добавить туда ещё одно сообщение, если позволяет логика программы, и с таймаутом. 

Да. У меня это выглядит так

/*Wait until a free space appears in the Tx Queue*/
bool UART_WaitFifoSpace_LL(UartHandle_t* node, uint32_t size) {
    bool res = false;
    if(node->init_done) {
        uint32_t cnt = 0;
        uint32_t up_time_start = TIME_GetMs();
        while(1) {
            cnt++;
            uint32_t spare = FIFO_GetSpare(&node->TxFifo);
            if(size <= spare) {
                res = true;
                break;
            }
            uint32_t up_time = TIME_GetMs();
            uint32_t diff = up_time - up_time_start;
            if(200 < diff) {
                res = false;
                break;
            }
        }
    } else {
        res = false;
    }
    return res;
}

Первая (очевидная, да, кэп!) - не использовать один и тот же UART для логов и для связи с чем-то другим.

Как же тогда один кабель Ethernet используется для сотен протоколов внутри трафика?

сама расставит мьютексы при инициализации драйвера и две задачи не попытаются писать в один UART каждая свое. 

У меня NoRTOS прошивка.

Спасибо. Надеюсь заметка поможет Вам в программировании микроконтроллеров.

 При этом число различных вариантов ошибок обычно ограничено, а если они повторяются быстрее отправки - сообщения о них можно объединять для экономии памяти. 

Гениально!

Мне на работе запрещено использовать FreeRTOS так как это "не доверенный код".

СLI в прошивке STM32, совмещённое с отладкой по UART - это претензия на псевдо-сакральное знание.

Этих CLI для ARMов полно.
Сорцы с реализацией уже скоро на заборах писать будут

Вон хоть у embox реализацию shell-а можно канибаллизировать

https://github.com/embox/embox/tree/e0cd6279507e413916a0dce526da87f486bb144c/src/cmds/shell

Information

Rating
151-st
Location
Санкт-Петербург, Санкт-Петербург и область, Россия
Registered
Activity