Перейти к содержанию
    

Timmy

Участник
  • Постов

    852
  • Зарегистрирован

  • Посещение

Весь контент Timmy


  1. STM32F0x2 и USB double-buffer

    Было бы любопытно посмотреть на лог, описывающий последовательнось и времена переходов между состояниями регистра USB_EPxR. То есть программируете старт передачи, все прерывания должны быть всё время теста запрещены, и опрашиваете где-нибудь полсекунды USB_EPxR, при любых изменениях записывая в лог-вектор новое состояние и время изменения из системного таймера. А также сбрасывая CTR_TX, если он появится. Потом лог-вектор срисовать в отладчике или выплюнуть через консоль. В результате экспериментов я установил, что в USB контроллере есть скрытый бит, который определяет, как интерпретируются сочетания SW_BUF/DTOG 0/0 и 1/1 - либо как два пустых буфера, либо как два занятых. Этот бит приходится восстанавливать программно - после переключения SW_BUF - два занятых, после чтения единичного CTR_TX или начальной инициализации - два пустых. То есть в исходном состоянии 1/0 || 0/1 можно набить данными один свободный буфер, переключить SW_BUF, и новое состояние окажется 0/0 || 1/1, однако оно будет означать два занятых и готовых к передаче буфера, а в мануале про это ничего не написано.
  2. Чтобы распределять пины, я в OO Calc нарисовал простыню - в колонках пины, в строках периферийные устройства, в клетках - возможные соединения, закодированные одной буквой/цифрой(например, для SPI - MISO - I, MOSI - O, SCK - K, CS - C, SS - S). Сразу все возможности видны на одном листе.
  3. STM32F0x2 и USB double-buffer

    Я использовал DBL_BUF на F103, и всё работает нормально. В мануале, к сожалению, слишком куцое описание этого режима, а в HAL реализация двойных буферов, мне кажется, забагована. Баг в том, что обработчик прерывания должен уметь при необходимости обслуживать минимум два буфера за один вход в прерывание, если контроллер того требует. Отличие моего от вашего алгоритма в том, что я при инициализации заполнял SW_BUF/DTOG_TX нулями, и только потом, когда уже установлен бит DBL_BUF, переключал SW_BUF, чтобы начать передачу одного буфера, это различие может оказаться важно. UPD: Могу предположить, что у вас случилось: вы инициализировали SW_BUF/DTOG_TX в 1/0, потом заполнили буфер данными и переключили SW_BUF(в нуль). В таком случае контроллер совершенно справедливо отправит два буфера, просто из куцого мануала этого не понять.
  4. В случае Cortex-M требуемый размер стека не увеличится, так как его переключатель контекстов использует из стека прерываний только одно слово, и оно и сейчас используется в точке с разрешёнными прерываниями.
  5. gcc есть под mico-8, но код там не очень эффективный получается из-за страничной адресации памяти.
  6. Всем привет! Обратил внимание на следующую вещь: stack_item_t* OS::TKernel::context_switch_hook(stack_item_t* sp) { CONTEXT_SWITCH_HOOK_CRIT_SECT(); ProcessTable[CurProcPriority]->StackPointer = sp; sp = ProcessTable[SchedProcPriority]->StackPointer; #if scmRTOS_CONTEXT_SWITCH_USER_HOOK_ENABLE == 1 context_switch_user_hook(); #endif CurProcPriority = SchedProcPriority; return sp; } SchedProcPriority - volatile, читается дважды без создания локальной копии, что приводит к необходимости обязательно запрещать прерывания перед вызовом context_switch_hook() или в CONTEXT_SWITCH_HOOK_CRIT_SECT(). Иначе в случае прерывания с перепланировкой между двумя чтениями SchedProcPriority может призойти переключение на один просесс, а в CurProcPriority запишется другой процесс и всё развалится:). А вот если сделать локальную копию SchedProcPriority, то, например, для Cortex-M прерывания при переключении контекста можно и не запрещать. И ещё кусочек: if(p->Timeout > 0) { if(--p->Timeout == 0) { set_process_ready(p->Priority); } } Неиспользование локальной копии p->Timeout приводит к её двойному чтению, в данном случае без тяжёлых последствий, просто неоптимально по длине кода.
  7. В вашем случае неконтролируемая задержка клока по цепям BUFG составила 3.8ns, она более, чем в два раза длиннее окна валидных данных, тут никакие констрейны не помогут(ну разве что неправильные:) ), надо использовать более быстрое тактовое дерево(BUFIO и т.п.) и/или компенсацию задержки с помощью IDELAY/DCM/PLL, вопрос обсасывали здесь уже раз десять.
  8. Если максимальная частота ниже примерно 10000 четвёртых цикла в секунду, то 32 энкодера можно и на микроконтроллере обсчитать с антидребезгом, если выше - можно использовать Lattice MachXO на 1200LE, туда точно всё влезет.
  9. А смысл в этом какой? Вообще, если хочется странного, можно LUTы описывать "руками". То есть описываете на HDL модуль с нужной логической функцией, ставите этому модулю атрибут (* LUT_MAP="yes" *), и, может быть, будет вам счастье. А может, всё равно оптимизирует:).
  10. Конечно, при синтезе функции на LUT все константные входы отключаются от LUT за ненадобностью, однако их значения правильно учитываются. А вы что хотите?
  11. Действительно, ТСу тоже надо поставить Independent, это значит, что два АЦП будут работать независимо.
  12. Советую сделать для начала без DMA, по прерыванию EOC, и включить останов таймера при входе в отладчик, так гораздо понятнее станет, что происходит. А, я не знаток Хала, но вы вроде врубили Continuous mode, поэтому АЦП после запуска всегда будет дубасить на максимальной скорости, игнорируя таймер.
  13. Не могли бы вы подробно прокомментировать вот эту конструкцию? process (clk, reset, enable, tmp) --process (clk) begin if (clk'event and clk='1') then elsif reset = '0' then tmp <= (others=>'1'); elsif enable = '1' then for i in 0 to 30 loop tmp(i+1) <= tmp(i); end loop; tmp(0) <= tmp(31) xor tmp(21) xor tmp(1) xor tmp(0); end if; end process;
  14. stm32 без cmsis

    Ставить кучу заглушек на все прерывания не обязательно. Младшие 8 бит PSR содержат номер текущего прерывания, так что одного DefaultHandler с бесконечным циклом достаточно для идентификации всех прерываний. Единица в младшем бите адреса перехода указывает, что переход происходит на Thumb код, а не ARM код, так и должно быть.
  15. А не пробовали с клавиатуры ввести цифрами нестандартный baudrate? Очень интересный квест получается:). Но это ещё ладно, один раз ввёл и всё, к сожалению HTerm тупо зависает при переключении между окнами и не очень большом потоке данных - 1000 строк в секунду по три символа+CR/LF. Так что не годится, пользуюсь realterm, он тоже не без греха, но не настолько.
  16. Да, глянул, там внутренние подтяжки есть, поэтому не внешние не нужны.
  17. Причиной может быть звон на тактовой линии JTAG из-за отсутствия последовательного резистора и плохой разводки. Кстати, вы уверены, что JTAG не надо резисторами подтягивать для правильной работы при пустом разъёме?
  18. При симуляции будет ошибка, так как значение d одновременно присвоится переменным q1 и q2 в одном дельта-цикле. Надо строчки поменять местами, тогда никаких проблем с симуляцией не будет. Также это может создать ошибки при синтезе, так как использован нестандартный способ описания регистров, который может "удивить" синтезатор:).
  19. Аналогом always является process. Аналогом @(posedge clk) является wait until rising_edge(clk). А вот аналога if rising_edge(clk) в Верилоге нет и не может быть из-за отсутствия концепции сигналов, хранящих состояние, бывшее в предыдущем дельта-цикле. Зато Верилог симулируется в 10 раз быстрее:).
  20. Вероятно, к o_data снаружи ещё один драйвер с нулями подсоединен. В моделсиме есть команда просмотра всех драйверов сигнала, так что легко найти, что это.
  21. В ветку под rising_edge(clk) процесс может попасть только при событии от сигнала clk, а поведение ветки под сбросом зависит только от сигнала сброса, таким образом, события от других сигналов не заставят такой процесс что-либо делать, поэтому нет смысла включать другие сигналы в список чувствительности.
  22. Удлинение пути сброса могло привести к нарушению констрейнов на скорость распространения сигнала сброса, у вас они проверялись?
  23. Если придут два события сразу, они обработаются в двух последовательных входах в обработчик прерывания. Вообще, вариант от Nixon является наилучшим универсальным и имеет смысл при использовании подгрупп приоритетов прерываний, и принадлежности прерывания I2C не к самой приоритетной подгруппе. В этом случае может быть целесообразно выскочить из обработчика прерывания как можно скорее, чтобы передать управление обработчику более привилегированной подгруппы, если возникнет запрос на него. Во всех прочих случаях вариант Nixon, как и большинство универсальных решений :) , создаёт более длинный код и большее время выполнения при одновременной обработке нескольких событий.
  24. IOWR нельзя ничем заменять, так как в Ниосе разные инструкции для записи в память и в порты ВВ(в этом случае отключается кэширование/буферизация).
  25. Приведу пример, где запись reg <= reg имеет смысл. always @(posedge clk)begin if(condition1)rg <= s1; if(condition2)rg <= rg; end Таким образом, condition2 отменяет сделанные выше присваивания регистру. Других осмысленных вариантов что-то не приходит в голову.
×
×
  • Создать...