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

    

Arlleex

Участник
  • Публикаций

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

  • Посещение

Репутация

0 Обычный

Информация о Arlleex

  • Звание
    Господин Никто

Контакты

  • Сайт
    http://
  • ICQ
    0

Посетители профиля

2 436 просмотров профиля
  1. SAME70Q21 rev.B - GMAC не работает на TX

    С этим МК не довелось работать, но есть идеи. Вы сами все регистры пишете? Обычно множество функций определяется внешней аппаратной обвязкой PHY. Есть уверенность, что в регистрах автосогласования и выбора режима дуплекса выставлены правильные значения? А откуда взялись некритичные отличия при одинаковом софте? А если сравнить дампы всех регистров в PHY? Вангую, что схема разводки PHY-уровня все-таки немного отличается от отладочной платы. И где-то из-за этого принудительно отключен режим выбора полного дуплекса. Кстати, что говорят параметры сетевой карты при подключении к двум девайсам? Скорость и режим дуплекса разные? Одинаковые?
  2. stm32 i2c

    Однако, просто очень странно, что сам производитель рекомендует делать >9 тактов по SCL при высоком SDA, а не формировать стоп-условия. https://www.nxp.com/docs/en/user-guide/UM10204.pdf Как я понимаю, первый случай (SCL залипла в 0) возможен только в ведомых на шине, поддерживающих технологию clock stretching-а. И тут спасет только вход сброса этой микросхемы (если он вообще имеется; как показывает практика, таких устройств меньше, чем обделенных таким входом), либо внешний перетык питания этой микросхемы (как когда-то я делал на одном из своих девайсов). Второй случай (SDA залипла в 0) спасается подачей 9 циклов синхронизации по линии SCL. И вот в течение этих клоков линия SDA должна подняться вверх. А если не поднялась - простите/извините, используйте аппаратный сброс (если есть), либо рубите канаты питание. Для 10-битной адресации логично подавать больше синхроимпульсов для получения такого же эффекта, выводящего из коматоза. В общем, никакой 100% гарантии. Так вот. Если залип SDA в 0, то стоп-условие, ИМХО, вряд ли поможет, так как при этом мы должны уметь формировать фронт на SDA. А он залип. А им надо дернуть. А он насильно притянут ведомым к 0. Вот картинка: Более того, если SCL еще можно сделать выходом типа push-pull (и то только для ведомых, не поддерживающих clock-ctretching), то SDA сделать push-pull нельзя вообще никогда, только open drain, т.к. шина данных двунаправленная, и при залипании шины в 0 (ведомый активировал нижний ключ входного/выходного драйвера) переводить драйвер мастера шины в push-pull и последующая выдача лог. 1 на этой линии может поджарить драйверы или в подчиненном, либо в мастере (МК). Тогда уж, ИМХО, совсем правильная процедура сброса будет включать сначала подачу 9 (или больше) импульсов синхронизации на SCL при отпущенном SDA, а затем, попутно проверяя состояние SDA входным регистром GPIO, поймав на SDA лог. 1, дать стоп-условие.
  3. stm32 i2c

    Я делал так, как рекомендует сам разработчик интерфейса (NXP). 1. При обнаружении зависания линии отменяю транзакции по этой шине. 2. Выключаю модуль I2C, деактивирую и перенастраиваю GPIO на режим ручного управления без изменения типа выходных драйверов. 3. Даю больше 9 стробов по линии SCL. 4. Выключаю синхронизацию модуля I2C. 5. Сбрасываю модуль I2C в регистрах RCC. 6. Заново инициализирую модуль (включение синхронизации, настройка GPIO и т.д.). Такую последовательность я провожу как при старте ПО, так и в процессе работы девайса при обнаружении заклинивания.
  4. Печально Не плодя тем, еще хотел бы осветить один момент. Пишу файл startup.c с константным массивом, определяющим таблицу векторов прерываний: typedef struct { #define INT_OPERATION_CODE 0x82 u8 INTOperationCode; void (*Handler)(void); }TISRVector; extern void ISR_ResetHandler(void); extern void ISR_TrapHandler(void); extern void ISR_TLIHandler(void); ... extern void ISR_NVMHandler(void); static const TISRVector ISRVectorTable[] = { {INT_OPERATION_CODE, ISR_ResetHandler}, {INT_OPERATION_CODE, ISR_TrapHandler}, {INT_OPERATION_CODE, ISR_TLIHandler}, {INT_OPERATION_CODE, ISR_AWUHandler}, {INT_OPERATION_CODE, ISR_ClockHandler}, {INT_OPERATION_CODE, ISR_EXTI0Handler}, {INT_OPERATION_CODE, ISR_EXTI1Handler}, {INT_OPERATION_CODE, ISR_EXTI2Handler}, {INT_OPERATION_CODE, ISR_EXTI3Handler}, {INT_OPERATION_CODE, ISR_EXTI4Handler}, {0, 0}, {0, 0}, {INT_OPERATION_CODE, ISR_SPIHandler}, {INT_OPERATION_CODE, ISR_TIM1FirstHandler}, {INT_OPERATION_CODE, ISR_TIM1SecondHandler}, {INT_OPERATION_CODE, ISR_TIM2FirstHandler}, {INT_OPERATION_CODE, ISR_TIM2SecondHandler}, {0, 0}, {0, 0}, {INT_OPERATION_CODE, ISR_USARTTxHandler}, {INT_OPERATION_CODE, ISR_USARTRxHandler}, {INT_OPERATION_CODE, ISR_I2CHandler}, {0, 0}, {0, 0}, {INT_OPERATION_CODE, ISR_ADCHandler}, {INT_OPERATION_CODE, ISR_TIM4Handler}, {INT_OPERATION_CODE, ISR_NVMHandler}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, }; Хочу теперь сделать хитрость. Чтобы в разных проектах заново не добавлять/удалять только нужные обработчики, я (как видно выше) определил для линкера все символы (имена обработчиков). Однако, как и следовало ожидать, при сборке проекта и отсутствии определенных обработчиков (их нет в таблице символов линкера), вылезли ошибки типа Что бы я хотел: при отсутствии обработчика в проекте, считать, что он для текущего проекта и не используется, и подставить вместо этого имени значение 0 (хотя это и не так важно). В Keil для этого существовала опция [weak], которая, будучи определенной рядом с именем, указывала, что, если этот символ будет определен в проекте, то использоваться будет именно он. Если нет - то символ со спецификатором [weak]. Является ли стандартной фишкой компоновщика наличие команды, заставляющей обратить ненайденные символы в 0 или другое известное значение, или это бородатый вымысел и такого в принципе не предусматривается? Беглый взгляд на описание компоновщика под Cosmic прямого ответа не дает.
  5. Приветствую! Пишу тут описание регистров периферии для одного МК (STM8, STVD/Cosmic). Бывает так, что между двумя регистрами одной и той же периферии или блока находится пустое пространство (резерв). Так вот, в местах, где такие "дыры" по пару байт, я пользуюсь безымянными битовыми полями: typedef volatile struct { u8 CR1; u8 CR2; u8 NCR2; const u8 FPR; const u8 NFPR; u8 IAPSR; u16 : 16; u8 PUKR; u8 : 8; u8 DUKR; }TNVM; Но есть периферия, между регистрами которой очень много пространства (больше килобайта). Пытался сделать так: u8 : 95856; Однако, даже если писать более короткие размеры u8 : 16; компилятор кричит на невозможность создания такого битового поля: При этом открываю Dev-C++, копирую туда тот же самый код и компиляция проходит успешно (без ошибок, но с предупреждениями). Кто-нибудь знает наиболее красивый способ объявить безымянную пустышку в структуре в произвольное количество байт, чтобы при доступе к элементам с включенной функцией автозавершения кода это пустое место не светилось никакими "Reserved1" и т.д.? Либо что-то типа безымянного массива (правда, я о таких не слышал). Решение нужно кроссплатформенное стандартное P.S. Раньше так и делал - в нужном месте объявлял массив нужной размерности и давал ему имя Reservedx, x = 1, 2...N. Но сейчас ищу способ не захламлять список регистров при всплывающей подсказке.
  6. Размышления на тему TCP/IP.

    Пока существуют ардуино-строители и всякие WizNet-писатели, я без работы не останусь Кстати, есть МК со встроенными MAC+PHY, поэтому нужен будет лишь внешний разъем 8P8C (с трансформатором внутри).
  7. Cosmic IdeaSTM8 и тип INT

    Я лично определил для себя типы известной размерности и их пользую. Либо всякие unit32_t, либо пишу свои typedef unsigned long u32 (как пример), в соответствии с документацией на компилятор.
  8. Я вот когда модули для лаборатории делал, себе одну платку отладочную (макет), естественно, спаял и оставил. На ней я применял F429. Сейчас запаяна туда H753, но допаять десяток конденсаторов и запустить как-то не хватает стимула ИМХО, артефакты пропадут, связанные с медленной прорисовкой. Да и поэкспериментировать не сильно большая проблема, полгода назад H753 вышел мне даже дешевле, чем F429. Покупал в Терраэлектронике, но сейчас у них дороговато. Не думаю, что плату переразводить Вам придется, хотя, вроде, у них несовместимость в 100-выводных корпусах. У меня LQFP-176...
  9. Предлагаю тогда не Cortex-M, а Cortex-A. Например, RZ/A1H от Renesas: https://www.renesas.com/us/en/products/microcontrollers-microprocessors/rz/rza/rza1h.html или тот же Zynq 7015 - на ПЛИСе поднимите собственное графическое ядро с желаемым интерфейсом, а 2 Cortex-A9 задействуете по остальным функциям. Никаких линуксов, естественно, не потребуется.
  10. Хотя, я тут подумал... Данные из руководства по программированию не будут противоречить только в следующем случае. Производитель дает свободу выбора положения начала участка в 64 килобайт для размещения ОЗУ, которое может быть вплоть до 16 мегабайт. Но аппаратно выводится 16-битная адресная шина для этого участка, поэтому адресоваться могут только 64 килобайт произвольного, но заданного производителем диапазона. Накидал картинку, как я это вижу. Пишите, согласны, или нет - самому интересно Итак, допустим, адресное пространство команд, как и обещал производитель, 16 мегабайт. Оно слева на картинке. Допустим (самый тупой случай, но он отражает возможность любого положения ОЗУ), Flash начинается до адреса 0x110000, идет себе, идет, и тут вклинивается ОЗУ - по адресам 0x110000-0x11FFFF размещается 64 килобайт пространства ОЗУ, и физически она адресуется по адресам 0x0-0xFFFF 16-битной шиной. Просто контроллер, обращаясь к ОЗУ, будет реально обращаться к адресу со смещением 0x110000. А при доступе к Flash, контроллер адресов всего лишь внесет поправку при доступе к ячейкам, превышающих адрес 0x110000 на объем области для ОЗУ. То есть, если мы хотим адресовать Flash по адресу 0x110001, то физически контроллер сформирует на 24-битной шине к Flash адрес 0x120001. Лишь в этом случае документация не противоречит сама себе и своим картинкам. Подтверждается это тем, что документация гарантирует наличие Гарвардской архитектуры с ненакладываемыми диапазонами адресов в едином адресном пространстве:
  11. Дык самое интересное - утверждается, что область данных тоже 16 мегабайт. Про размещение ОЗУ в конкретной реализации понятно - она (как и вся регистровая модель, Flash, EEPROM и т.д.) сейчас лежит в нулевой секции и, по факту, инструкции с трехбайтной адресацией не нужно использовать. Но просто если я (допустим, как производитель МК) посчитал нужным разместить ОЗУ в конце 16 мегабайтного участка, то столкнулся бы с откровенной ложью товарищей из ST? Ведь область данных - это область данных, и вся она подразумевает возможность подключения RAM к любому участку этой области, как я понимаю. А 16-битная выходная шина адреса области данных как бы намекает, что хотелки нужно бы обрезать Печальненько... Где? К Flash - понятно - все честные 24 бита. К ОЗУ выходная шина адреса имеет 16-битную глубину.
  12. Плодить темы не хочу, отпишусь тут. Чем больше читаю Programming Manual, Datasheet, Reference Manual, тем больше понимаю, что авторы явно что-то путают, недоговаривают, опускают важные детали и особенности, которые могут сыграть злую шутку при разработке (на ассемблере). В общем, в руководстве по программированию CPU, на странице 19 написано: И вот картинка этой шинной архитектуры: Во всех местах, где не лень, в документации пишут, что адресное пространство данных 16Мбайт. Я, может быть, и поверю, только почему на рисунке 4 результирующая шина адреса к области данных идет 16-битная? Как 16 бит адресовать 16 мегабайт могут? И вот в документации куча нестыковок, хочется забросить это дромыхло уже
  13. Как работает DMA в STM32?

    Почему же? Времени между двумя соседними установками запросов на DMA-транзакции от UART, в сравнении с частотой работы контроллера DMA, настолько много, что, вклинившийся между ними запрос от модуля SPI будет обработан между транзакциями от UART, так что Вы этого даже не заметите. В случае же, когда модули UART и SPI выставят линии запроса DMA одновременно (или наложатся во времени), первым будет обработан тот, чей приоритет выше. А вот другое дело, если Вы работаете с высокоскоростными источниками/приемниками, например, памятью. В этом случае, при условии, что контроллер один (к примеру, DMA1), низкоприоритетный запрос будет отложен до лучших времен (пока более высокоприоритетный не будет полностью отработан), поскольку низкоприоритетный запрос не сможет "вклиниться" между двумя последовательными запросами более высокого приоритета.