Jump to content

    

KnightIgor

Участник
  • Content Count

    754
  • Joined

  • Last visited

Community Reputation

0 Обычный

About KnightIgor

  • Rank
    Знающий

Контакты

  • Сайт
    Array
  • ICQ
    Array

Информация

  • Город
    Array

Recent Profile Visitors

2928 profile views
  1. Тогда я лично в потемках. Явно кто-то грузит процессор так, что прерывание не успевает выбрать регистр данных, и возникает переполнение. Это может быть связано с длинной пост-обработкой принятого прерыдущего байта в самом прерывании. Попробуйте "зациклиться" в прерывании по приему, пока не упадет флаr RXNE: то есть, не "сработало прерывание по RXNE - байт выбран, обработали, вышли", а "сработало прерывание по RXNE - выбираем байты в цикле с проверкой RXNE, пока он не упадет, потом вышли". Еще идеи: 1. Наверное AT_ExecuteCommand() посылает что-то через UART/SPI? Это то, о чем я говорил в части интенсивной передачи и DMA. 2. Может ваш приемный буфер, куда складываются принятые байты, по глубине равен 1? Типа недоглядели какой #define...
  2. 1. Кто писал _ReceiveData? Может там есть код, который запрещает прерывания на время? 2. _SendInt посылает через прерывания? Если да, то может приоритет этого прерывания выше приема UART, да еще в прерывании достаточно длительная предобработка ведется? Попробуйте закомментировать именно _SendInt, а если есть полный контроль над этой функцией, попробовать передавать с помощью DMA.
  3. Как я понял, есть два источника данных. Оба работают по прерыванию. Один из источников переполняет буфер приема. Может с приоритетами прерываний поиграть?
  4. А что там за тема с PLL в GD32? Бинарник от STM32 не попадет в цель?
  5. Кстати, о совместимости. STM нумерует периферию с 1 (ADC1, ADC2...), а GD32 - c 0. Это будет веселье на уровне исходников адаптировать под GD32. Кто-нибудь грузил бинарник от STM32 в аналогичный GD32?
  6. Я в описании процессоров интересующей меня линейки GD32F103 с удивлением обнаружил, что у них нет.... USB! https://www.gigadevice.com/microcontroller/gd32f103rct6/ Хотя в описании драйверной библиотеки есть поддержка USBD... Не ясно, где недоразумение.
  7. Шутку я знаю. Спасибо за общие фразы.
  8. Не поверите, но работая полный день над другими проектами, остается мало времени, и я пытаюсь найти ошибку самостоятельно, поскольку здесь, кроме общих поучений в виде введения в принципы FIFO и иных заявлений типа "она неправильно построена", надеяться на совет не приходится.
  9. Админ убил мою вставку, она была слишком длиной. По поводу "нормального подхода" с общим запретом прерываний - у меня тут принципиальная позиция, что это топорно. Меня так учили. Во времена, когда со всеми ресурсами было плохо.
  10. Эксклюзивный доступ в Cortex не подходит для моих целей: внутри прерывания он смысла не имеет, а для синхронного потока в данном приложении - тоже. В Cortex эксклюзивный доступ работает топорно: если после ldrex до strex произошло ЛЮБОЕ прерывание, strex вернет "ошибку". С точки зрения синхронной процедуры, при ее попытке что-то изменить невовремя, она получит отлуп от strex и будет вынуждена зациклиться, пытаясь снова и снова. Пусть это фобия, но я не люблю зацикливать на непонятно сколько времени куски синхронного кода в моей системе кооперативной многопоточности. Кроме того, ЛЮБОЕ прерывание, даже не относящееся к области интереса конкретного "драйвера" периферии, будет порождать отлупы. В результате, все становится не лучше запрета-разрешения прерываний из синхронного цикла, что я тоже считаю топорным подходом. Есть вариант через SVC. В моей системе я это действительно использую для некоторых специфических целей, когда уж точно надо что-то исполнить эксклюзивно в синхронной части (например, атомарное вычисление, или надо ткнуть какой-то процесс, и чтобы не влезло прерывание между делом), но конкретно для "драйвера" UART|SPI|общего потокового устройства это overkill, если тема решена уже проще. Еще раз вернемся к теме: оптимизация под gcc что-то рушит. А оптимизация под KEIL - нет! С бОльшей вероятностью - какая-то глубоко законспирированная ошибка в моем коде. Но есть вероятность и того, что это косяк в gcc: кто там писал о проблемах в IAR?
  11. Дело не в потере значения R1, а в том, что [R1] указывает на разделяемый ресурс, как-то счетчик, индекс или указатель. Например, пусть в str R0,[R1] R0 содержит новое значение, которое планируется записать по адресу [R1], равное 1. Перед str произошло прерывание, которое запишет по адресу [R1] значение 2, а после возврата str запишет туда 1. И все рухнуло. Я должен уточнить, что мой код предполагает не просто FIFO с одним писателем и одним читателем, а по меньшей мере двумя писателями. Возможно, вначале я не достаточно ясно выразился - сорян, - в результате чего мне и пишут, что "Вариант с двумя указателями позволяет строить кольцевые буфера с одним писателем и одним читателем без дополнительных средств синхронизации потоков (типа запрета прерываний)", хотя речь с моей точки зрения идет о двух писателях. Дело в том, что изначально код был написан для поддержки stdio (терминала), когда устройство подключено как непосредственно по UART, так и по USB с поддержкой виртуального COM-Port (CDC). То есть, символы могут приходить как от терминала, так и по USB. Конечно, с точки зрения реального управления вряд ли кто-то будет одновременно писать левой рукой в терминал, а правой - в другой терминал на виртуальном COM-Port, и пытаться выяснить, какая рука у него быстрее, но технически такое возможно, и нужно обезопаситься, чтобы система в целом не рухнула. Вот функция bufio_StoreChar(bufio_FIFO *FIFO, uint16_t c) как раз для этого и предназначена, и я не хотел внутри ее, если она вызвана из основного потока, запрещать какие-либо прерывания. Поэтому функция защищает критическую секцию флагом, а вот уже прерывание, которое имеет полный контроль над самим собой, в том числе - себя отложить, этот флаг анализирует и действует соответственно. Функция bufio_StoreChar() приведена еще раз ниже (сорри, админ потер мою вставку со всем кодом в предыдущих постах, т.к. она была слишком длиной): // ----------------------------------------------------------------------------- // // Stores a value to the software driven input (PC -> Device) FIFO buffer. // Returns -1 if no more place in the FIFO. // // CALLED FROM THE INTERRUPT HANDLER or // an external routine that wanna insert a value into the input buffer // int32_t bufio_StoreChar(bufio_FIFO *FIFO, uint16_t c) { int32_t res = -1; if (bufio_RXBufferReady()) { bufio_DRIVER* h = FIFO->HD; // to shorten the script if (FIFO->RX.size < 2) // store as byte _CAST_DATA_AS_B(FIFO->RX.data, FIFO->RX.idx) = res = (char)bufio_InputFilter(c); else // store as word _CAST_DATA_AS_W(FIFO->RX.data, FIFO->RX.idx) = res = bufio_InputFilter(c); idxplus(&FIFO->RX); // move index/counter within a critical section // (re)enable RX interrupt if being called not from an interrupt above if (!Called_From_ISR() && h && h->RIE) h->RIE(1); } return res; } Получалось, что если внутри критической секции сработало прерывание, оно увидит флаг и отложит себя (запретом), а функция выше при выходе просто переразрешает прерывание, и если оно было отложено, оно тут же сработает и доделает свое дело. Конечно, без запрета прерывания не обошлось, но это происходит в нем самом и действительно только тогда, когда это необходимо, а не каждый раз, когда происходит вызов к bufio_StoreChar() из основного потока. Это была моя основная идея "невмешательства" синхронного потока в систему управления прерываниями.
  12. Вот я уже заинтригован. Это в 8051 была команда xch, которая атомарная. В кортексе такого нет.
  13. например, читает прерывание, а пишет синхронный цикл. Что будет, если синхронный цикл выполняет ldr r0,[r1] add r0,#1 str r0,[r1], а прямо перед str рубануло прерывание, которое использует то, куда указывает [r1]?
  14. Даже не смешно. Я писал: "2. У меня не просто FIFO, но с атомарным доступом, который достигается флагами и основан на свойстве прерываний в 8051 и CMx, когда их можно, скажем так, отложить. При этом не нужно запрещать/разрешать прерывания глобально ( __enable_irq(), __disable_irq()) ". Конечно, чтобы двигать указатели/счетчик ВНЕ прерывания, я флаг устанавливаю, отмечая критическую секцию. В самом прерывании этот флаг анализируется и прерывание откладывается. Когда критическая секция завершается, она прерывание просто (пере-)разрешает. Происходит влет в прерывание и работа уже с новыми значениями указателей/счетчиков. То есть, запрет прерывания есть, но он происходит внутри самого прерывания, а не в синхронной части программы как бы извне.