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

AlanDrakes

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

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

  • Посещение

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


  1. Наталкивался на похожее поведение, когда память не успевала считывать данные из себя при слишком быстром тактировании ядра. Проверьте, что латентность Flash'а соответствует скорости ядра.
  2. Push-Pull. На ведомых устройствах это всегда вход, так что можно не бояться выставлять на нём любой логический уровень. Если вниз (5 -> 3.3) - резисторный делитель 1к/2к Если вверх (3.3 -> 5) - Mosfet (тот же N7002) и пара резисторов. Эпизодически, когда лень заморачиваться с количеством резисторов, ставлю с инверсией: В особо замороченых случаях, когда требуется сделать более "силовой" плюс - ставлю пару N + P. N-канальный тянет затвор P-канального к нулю, P-канальный подключает сток к питанию. Из минусов - требуется резистор подтяжка уже для P-канального.
  3. На F103 успешно работает вот такая конструкция ожидания завершения передачи последнего* байта: *(volatile uint8_t *)&(SPI2->DR) = Data; // Складываем байт while (!(SPI2->SR & SPI_SR_TXE)); // Ждём, пока не станет "Свободно" в буфере передатчика (иначе можно проскочить) while (SPI2->SR & SPI_SR_BSY); // Только после этого дожидаемся снятия флага "ЗАНЯТО, Л-Л-ЛЯ!" После этого данные гарантированно переданы и можно поднимать ножку. С DMA - можно использовать те же проверки, предварительно отключив сам DMA канал.
  4. Из простейшего (так как отображает, что чип видит): 1. Попробуйте снизить частоту тактирования до 1МГц (возможно слишком длинные провода, или что-то ещё в схеме) и слишком высокая скорость обмена его в итоге и ломает. 2. Попробуйте поменять опции подключения к чипу: Connect -> Under reset / With Pre-reset (должен быть подключен пин сброса). Reset -> Hardware reset. В некоторых случаях желательно подтягивать пин сброса чипа к напряжению питания (3.3В) дополнительным резистором на 1-4кОм. Пин VTarget желательно подключать. От него питаются выходные шинные буферы (в варианте STLink'а на Discovery - нет, но там напряжение должно быть близким, иначе тоже возникают разные интересные сбои).
  5. А ещё можно вызывать __INLINE__ функции. И даже функции описывать так же. Да в конце концов! static inline __attribute__((always_inline)) void stop(void) { PORTD &=~(1<<PIND7); PORTB &= ~(1<<PINB0); } И вызывать в коде "stop();". В результате на место вызова функици будет вставлено её развёрнутое тело - обе операции с портами.
  6. Макрос пытается выполнить два действия с портами? Может в этом случае изменить его на однострочный? #define stop PORTD &=~(1<<PIND7); PORTB &= ~(1<<PINB0) В таком случае будет производиться подстановка, условно, двух команд. А та конструкция должна вызывать у компилятора вопрос "Тут же всегда будет TRUE. Оптимизировать, что ли?"
  7. Кнопка "Изменить" внизу сообщения. А с ассемблером внутри ОС - довольно сложно. Если мне не изменяет память, то можно выделить переменные статически (внутри программы) через db - посмотрите хотя бы здесь. Либо же использовать вызовы ОС, в частности malloc / free для работы с виртуальной памятью. Либо же собирать bare-metal приложение, без всех возможностей ОС. Я так пытаюсь лениво подступиться к одному китайскому SoC кристаллу.
  8. Работать с локальными переменными на ассемблере - та ещё морока. А в среде операционной системы - так вообще. Самое простое объяснение - память, которую видит программа (адресное пространство) никак не связана с реальным адресным пространством, потому что MMU в уже запущеной ОС работает с таблицами адресов (в простейшем случае) и при обращении к памяти по адресу 0xDEADBEEF (допустим), в начале идёт поиск по таблицам адресов, затем выбирается блок памяти, на который диапазон ссылается, после чего идёт попытка обращения к этой памяти (например получилась страница в 4к по адресам 0xFOODC000 ~ 0xFOODCFFF). Вам... действительно нужен ассемблер? Проще же написать программу на Си под малинку. Компилятор сделает большую часть работы за вас. Лично я ассемблером наигрался на AVR'ках. Больше не хочется писать ВЕСЬ код на нём.
  9. У меня имеется подозрение, что писать в адрес 0x100 не удаётся и именно это вызывает исключение.
  10. В базе знаний описан процесс запуска контроллера и подготовки его к шифрованию. https://docs.espressif.com/projects/esp-idf/en/latest/esp32/security/flash-encryption.html В общем случае контроллер может работать в трёх режимах - обычный (flash не зашифрован), комплект разработчика (во flash записывается расшифрованная прошивка, которую после шифрует загрузчик) и release - готовое устройство. Прошивка на внешней флешке должна быть зашифрована (либо в устройстве). Зашить во FUSE блок ключ можно с помщью команды: espefuse.py --port port burn_key flash_encryption abc/key.bin Проверить состояние: espefuse.py --port port summary Если ключ в области FUSE забит вопросами: значит ключ есть и после перезагрузки содержимое внешней флешки будет зашифровано. Ну и процесс обновления по воздуху описан там же
  11. c99 - это стандарт. Компилятор, как правило, gcc В зависимости от архитектуры может быть с преффиксами, а может быть дефолтным. В моём случае, c99 находится в /usr/bin/c99, является алиасом на /etc/alternatives/c99, который является bash-скриптом, запускающим gcc с ключом -std=c99 Сделайте sudo apt-get install gcc
  12. ChaN пишет, что в самой FAT прописывается размер сектора и Windows* системы его поддерживают, но некоторые драйверы используют зашитое значение в 512. http://elm-chan.org/docs/fat_e.html А тут пробуют отформатировать обычную карту памяти под сектор с размером 4к. Вроди бы даже успешно. Но имеются ограничения - минимальное количество кластеров для файловой системы. https://askubuntu.com/questions/983546/trying-to-format-a-64gb-microsdxc-card-with-4096-bytes-per-sector Плюс, дескрипторы USB - нужно сообщать, что размер сектора не 512 байт, а 4к. Но вам это виднее - я только пару раз прикрутил пример от ST к проекту и оно даже заработало... как-то. Ужасно медленно и в режиме только чтения. И естественно, на 512-байтных секторах.
  13. Для одного проекта наваял простенький самописный загрузчик, прикрутил к нему UART и x-modem, чтобы каждый раз не разбирать устройство и не обновлять прошивку программатором. В какой-то момент, обновляя прошивку, случайно указал .elf файл вместо .bin и заметил это только когда залилось уже 190кБ из 96 😕 В общем, счётчик страниц на STM32F103C8T6 успешно крутанулся и записал в загрузчик мусор. Хотя вроди бы всё проверял перед записью. Оказалось, что нет. Так что от ошибок программиста никто не застрахован. И самое печальное, когда от своих ошибок не застрахован.
  14. Упс. А слово-то я перепутал, да 😞 На тех кристаллах, с которыми я имел дело, обычно интерфейс выведен плотненько в 4 пина. Так почему бы не вести их рядом? А потом на месте перекинуть как требуется для другого чипа. =]
  15. На однослойке проблемно. На двух слоях ещё можно. Просто все 4 дорожки вести группой, и уже по месту как-то менять их положение (перекидывать через резисторы-перемычки, например).
  16. Это не те частоты, на которых нужно заморачиваться ТАКОЙ магией. С дорожками до 10 см и разнице длин до 2-3 см это будет работать и так. Выравнивание нужно для синфазных пар. Но хорошим тоном будет вести дорожки рядом.
  17. TE - Tearing Effect - специальный пин, который взводится в 1 в тот момент, когда контроллер дисплея обновляет на матрице определённую строку. Ищите по даташиту соответствующий регистр. Возможно по "Tearing line" или похожему сочетанию. Используется для синхронизации вывода изображения из контроллера в память экрана для устранения эффекта полукадра. Регистр 0x44 - STE (Set Tear ScanLine ) - устанавливает линию, на которой будет генерироваться прерывание. Про эффект разрыва - смотрите пункт 10.8.3 Example 1: MPU Write is faster than panel read. В даташите, который имеется у меня, изображение-пример с данными кадра относится к 10.8.4 Example 2: MPU write is slower than panel read Не с именно этим контроллером, но похожую ситуацию ловил на ILI9341 Лично мне пришлось немного ухудшать тайминги работы с дисплеем перед чтением. Попробуйте вот такой код:
  18. Вы правы, я что-то не те функции взял. И, да. У 401 как раз старый блок I2C. Но фукнкции таки работают. Исправлюсь. Тут проект был меньше и в основном читает данные с датчиков. Собирается как раз под L051. I2C_ReadArray - читает как есть - это работает с AHT10. ИМХО - забавный датчик. Отправляем команду через запись трёх байт, ждём, читаем тупо массивом. I2C_ReadArray_from8 - аналогично EEPROM'у. Уже нормально работает с BMP(BME)280. Вычитывает массив, начиная с адреса [Addr] и складывает в память. ЗЫ: Вообще не люблю шину I2C. Кроме экономии проводов даёт только проблемы. То после подачи питания контроллер слишком быстро начинает работу с шиной (а некоторые хитро вы.... сделанные микросхемы ещё не очухались), то какой-то чип воспринял переходный процесс как START, то ещё что... Уууууу. То подтяжки слабые, то подтяжки сильные... И гнать шину нельзя. Хотя пара MAX17043 + M24C02 на шине пока что уживаются хорошо.
  19. Резистор-подтяжка какого номинала? Я бы выбрал около 1к, исходя из ваших замеров. Получаем: Кнопки отпущены - цепь разомкнута: Vadc = 3.3V (если питается от 3.3V). Нажата кнопка 1 [3к]: Получаем делитель напряжения 1:3; Vadc ~= 0.75*3.3V ~= 2.475V. [центральное] Нажата кнопка 2 [1k]: Получаем делитель напряжения 1:1; Vadc ~= 0.5*3.3V ~= 1.65V. [центральное] Нажаты кнопки 1+2 [3k || 1k]: Получаем делитель напряжения 1:0.77; Vadc ~= 1.27V [центральное] Нажата кнопка 3 [0]: Получаем... замыкание цепи АЦП на землю и напряжение около нуля. Читаем напряжение на пине каждые 10-20мс, фильтруем значения, усредняем пару-тройку выборок. Если напряжение более 0.2с стабильно в вышеописанных диапазонах (даём допуск 5-10%), то принимаем решение о том, что кнопка нажата. Если снова 3.3V - кнопки отпущены. Всё довольно просто. В теории. PS: Не забудьте добавить конденсатор фильтра на вход АЦП. Для такого делителя можно взять от сотен пикофарад до десятков нанофарад.
  20. Я подключал этот дисплей на шину SPI и отправлял данные блоками по 128 байт (дополнительно обрамляя их командами записи в определённые ячейки памяти, ибо похожий контроллер SH1106 не умел переходить на следующую строку - приходилось самому. А SSD1306 умеет, но команда ему не мешает - так что оставил как есть). И, да. Присоединяюсь к рекомендации Obam - слать блоками по 128 байт. Вообще, перепишите функцию отправки. У вас исходник под AVR, а тут всё же более продвинутая периферия - можно много чего сделать удобнее. VladislavS привёл в пример готовый код. Если хотите максимально просто - приложу свой. Не использует плюсы, всё на регистрах. Заточено под F401 (но I2C периферия в L05x не особенно отличается - проверил по референсу). У меня НЕ обрабатываются пограничные случаи, как отправка OVER 255 байт в устройство (т.к. столько не требовалось, да и микросхема EEPROM, под которую писал код, всего на 256 байт. Функции в случае ошибки при передаче возвращают -1 (0xFF), в случае успеха - 0.
  21. Посмотрите в сторону синхронного запуска через TIMx->SMCR - Slave mode control register. В reference manual'е как раз указывается, что данный регистр может использоваться для вашей задачи.
  22. Кто как, а у меня на L051 работает вот такой запуск I2C: I2C1->CR2 = (I2C_CR2_AUTOEND | DevAddr << 1 | I2C_CR2_RD_WRN | (DataToRead<<16) | I2C_CR2_START); Сразу пишем в регистр и адрес ведомого и автостоп (после нужного количества байт) и всё прекрасно срабатывает. Ещё раз убеждаюсь, что в L05x перенесли блок I2C от F030, а не из F407, где всё делалось через тыканье битов на каждое действие: Отправили старт? Шлём адрес. Отправили? Отлично. Ошибка?! Ах ты ж... ну ладно. Или Закончили отправлять байт? Отлично, продолжаем. Ошибка линии? Ну вот опять 😞 А тут? Стартуем на адрес XXXX, отправлять будем YYYY байт! После отправки - стоп. И всё! Знай только байты подкладывай. И иногда следи за флагами состояний.
  23. Отсюда АЦП на STM32 работает по принципу уравновешивания заряда, а не уравновешиванию токов, как АЦП на AVR чипах (во всяком случае тех, с которыми я работал). Если оставить пин АЦП болтающимся в воздухе, или же прицепить к нему конденсатор относительно небольшой ёмкости (сотни-тысячи пикофарад), то значения АЦП будут тянуться к середине шкалы (2047/4097), но и реагировать на наводки на этот самый пин. При большой частоте измерений ток, вытекающий из АЦП будет довольно значительным для резистора в 1МОм на вашей схеме. Я бы уменьшил его номинал до десятков кОм, либо поставил промежуточный буферный ОУ между C52-R88 и собственно АЦП.
  24. 1. Не делайте очистку проекта перед сборкой. 2. Не добавляйте файлы исходников (и заголовочников). 3. Не меняйте опции сборки через make menuconfig. И тогда проект будет собираться в режиме сборки изменений, а не в режиме полной сборки. Если не выполняется хоть одно условие - чаще всего в каталог в проектом был добавлен новый файл, либо удалён существующий - происходит полная перекомпиляция ВСЕГО. Да, бесит, особенно на слабых компах.
  25. У меня энкодер работает следующим образом: // TIM3 SMCR -> SMS = 011 // TIM3 CCER -> CC1P + CC2P TIM3->ARR = 402; TIM3->SMCR = (TIM_SMCR_SMS_1 | TIM_SMCR_SMS_0); TIM3->CCER = (TIM_CCER_CC2P | TIM_CCER_CC1P); TIM3->CNT = 200; TIM3->CR1 = TIM_CR1_CEN; EncVal = (TIM3->CNT >> 2); <...> if (EncVal != (TIM3->CNT >> 2)) { if (EncVal < (TIM3->CNT >> 2)) { OnKeyDown(9); // ENC- } else { OnKeyDown(10); // ENC+ }; EncVal = (TIM3->CNT >> 2); }; В общем, мне попались энкодеры, которые за один клик дают фактически два импульса (фронт на первом канале и спад на втором). С одной стороны - хорошо, с другой - интересная особенность. Потому значение делится на два. Случай переполнения цинично игнорируется (код тестовый).
×
×
  • Создать...