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

athlon64

Свой
  • Постов

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

  • Посещение

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


  1. STM32F746 FMC + LCD

    Оказалось, что первое обращение по указателю 0x64000000 отрабатывалось, а последующие пропускались. Причина во включенном кэшировании записи в Cortex-M7 для адресного пространства 0x60000000 - 0x7FFFFFFF. Решение - включить ремап на адресное пространство 0xC0000000-0xDFFFFFFF, где кэширование записи отключено HAL_EnableFMCMemorySwapping();
  2. STM32F746 FMC + LCD

    Коллеги, добрый день Использую STM32F746G (на плате StarterKit SK-STM32F746). Пытаюсь подключить используя FMC небольшой дисплей с параллельным интерфейсом, но перед подключением решил проверить логическим анализатором правильность выдачи сигналов на линии D0-D15, WR, RS, CS. Оказалось, что при записи по адресу в соответствующем банке памяти данные на D0-D15 не выставляются, WR, CS (в моем случае NE2) также не изменяют свои состояния. При обращении к памяти использую указатель 0x64000000 (1 банк, 2 подбанк). Все используемые ноги FMC инициализированы, скорость GPIO_SPEED_FREQ_VERY_HIGH. При этом если инициализировать SDRAM (которая уже есть на плате), то при обращении к адресному пространству SDRAM на шине данных сигналы появляются и SDRAM работает хорошо. Вроде всё просто, не понимаю что я мог упустить. Прошу вашей помощи
  3. Добрый день Возможно кто-нибудь сталкивался с коммерческими САПР для проектирования печатных плат, доступ к которым можно было бы арендовать на время? Скажем на 6 или 12 месяцев. Было бы интересно оценить целесообразность покупки такой аренды для не сильно большого проекта.
  4. Что именно не похоже? При частоте 100 КГц частоты атмеги в 1 МГц уже недостаточно, не говоря уже о 400 КГц
  5. После поднятия частоты атмеги всё заработало! Рекомендацию эту нашёл в документе "AVR311: Using the TWI module as I2C slave" - частота работы avr должна быть хотя бы в 16 раз выше частоты работы twi.
  6. В общем в итоге имею вот что. После включения питания магнитолы (и атмеги) сразу попадаю в обработчик TWI с TWSR=0x00, переинициализирую TWI. Больше в обработчик не попадаю. Тем временем шина в магнитоле работает, TDA7563 включается. Напоминаю, что атмега и TDA7563 сидят на одной шине с одинаковыми i2c-slave адресами. Возможно с этим связана проблема, хотя, с моей точки зрения, так делать можно и если выдавать мастеру в данных только байты = 0xFF, то всё должно работать. Или я не прав? Ещё завтра попробую поднять частоту атмеги до 8МГц, сейчас 1МГц
  7. Спасибо за совет, это я попробовал сразу же :) тоже накалывался, и не раз но в даташите на атмегу и TDA всё однозначно написано, нужно именно TWAR = 0x6C << 1;
  8. В общем выяснилось, что была ошибка в обработчике прерывания от TWI, неправильно разбирался регистр TWSR, из-за чего автомат TWI оказывался в непонятном состоянии. Для магнитолы это выглядело как 0 на SDA и включаться она отказывалась. Теперь другая проблема - атмега не фиксирует обращений по i2c-адресу TDA7563 (0x6C). Пока разбираюсь.. На случай если кому то будет интересно глянуть: Инициализация TWI: void Init_Twi(void) { __disable_interrupt(); TWAR = 0x6C << 1; TWCR |= (1 << TWEN) | (1 << TWIE) | (1 << TWEA); __enable_interrupt(); } Обработчик: #pragma vector=TWI_vect __interrupt void TWI_ISR() { LED_Flash(5); switch (TWSR & 0xF8) { //=== Передача данных case 0xa8: // Принят свой адрес, будет выдача Data. case 0xb8: // Выдан байт Data, получен ACK. case 0xc0: // Выдан байт Data, получен NACK. TWDR = 0xFF; break; //=== Прием данных case 0x60: // Принят свой адрес, будет прием Data. TWI_Buff_Idx = 0; break; case 0x80: // Принят байт Data, выдан ACK. case 0x88: // Принят байт Data, выдан NACK. Tst[TWI_Buff_Idx] = TWDR; TWI_Buff_Idx++; break; case 0xa0: // При приеме в своем адресе был принят STOP или RESTART. CheckTWIbuff(); break; default: break; } TWCR |= (1 << TWINT); // Сброс флага прерывания. }
  9. Приветствую всех Делаю устройство на atmega8, которое подключается к шине i2c автомагнитолы и являясь i2c-слейвом, перехватывает команды включения/выключения встроенного усилителя на TDA7563. i2c в магнитоле 3,3-вольтовая. Так вот, атмегу запрограммировал, она исправна, тактируется от внутреннего генератора 1МГц. Использую аппаратный TWI, i2c адрес установил как у TDA, но столкнулся в внезапной проблемой. Подключаю свою плату к SDA, SCL и GND магнитолы и шина магнитолы перестаёт работать, т.к. уровень на SDA, SCL держится в районе нуля. Сама атмега не запитана (пробовал и запитывать), т.е. VCC в воздухе. При отключении GND магнитолы от атмеги, работа шины восстанавливается, а на GND атмеги напряжение ~3В. Плата атмеги простейшая, стабилизатора нет (планирую питаться от 3,3В магнитолы, есть только 2 отладочных LED и всё. КЗ между SDA, SCL и GND атмеги нет.
  10. Корпус/шасси 2U

    Излазил каталог Schroff и ещё нескольких производителей, не могу найти каркас который изображен на фото. В принципе сильно похож на euroPac PRO, но у europac высота бывает только 3 или 6 юнитов. Те модели, которые предлагаются в 2U, как правило не имеют рейку с отверстиями ближе к передней панели (нужно для крепления внутрь модулей). Также обычно на боковых стенках отсутствует направляющая для удобного монтажа/демонтажа в стойку.
  11. Видимо пропуск прерывания происходит из-за того, что при обработке прерывания от одного таймера между строками uint32_t timer_status = *pTIMER_STATUS; и *pTIMER_STATUS = 0x00FF00FF; устанавливается флаг TIMIL другого таймера и, соответственно, сразу сбрасывается без обработки. Хотя, казалось бы, вероятность такого события чрезвычайно мала) Переписал обработчик следующим образом #define TIMER_STATUS_FLAGS_MASK_T0 0x00000001 #define TIMER_STATUS_FLAGS_MASK_T1 0x00000002 #define TIMER_STATUS_FLAGS_MASK_T2 0x00000004 #define TIMER_STATUS_FLAGS_MASK_T3 0x00000008 #define TIMER_STATUS_FLAGS_MASK_T4 0x00010000 #define TIMER_STATUS_FLAGS_MASK_T5 0x00020000 #define TIMER_STATUS_FLAGS_MASK_T6 0x00040000 #define TIMER_STATUS_FLAGS_MASK_T7 0x00080000 ISR(ivg13_isr) { ssync(); if (*pTIMER_STATUS & TIMIL0) { *pTIMER_STATUS = TIMER_STATUS_FLAGS_MASK_T0; ssync(); } if (*pTIMER_STATUS & TIMIL1) { *pTIMER_STATUS = TIMER_STATUS_FLAGS_MASK_T1; ssync(); } if (*pTIMER_STATUS & TIMIL2) { *pTIMER_STATUS = TIMER_STATUS_FLAGS_MASK_T2; ssync(); } if (*pTIMER_STATUS & TIMIL3) { *pTIMER_STATUS = TIMER_STATUS_FLAGS_MASK_T3; ssync(); } if (*pTIMER_STATUS & TIMIL4) { *pTIMER_STATUS = TIMER_STATUS_FLAGS_MASK_T4; ssync(); } if (*pTIMER_STATUS & TIMIL5) { *pTIMER_STATUS = TIMER_STATUS_FLAGS_MASK_T5; ssync(); } if (*pTIMER_STATUS & TIMIL6) { *pTIMER_STATUS = TIMER_STATUS_FLAGS_MASK_T6; ssync(); } if (*pTIMER_STATUS & TIMIL7) { *pTIMER_STATUS = TIMER_STATUS_FLAGS_MASK_T7; ssync(); } }
  12. Добрый день У меня в проекте на BlackFin BF523 используются 3 таймера общего назначения с генерацией прерывания по достижению значения из TIMERx_PERIOD. Случайно обнаружил что периодически происходит пропуск обработки интервала счёта. Пересмотрел ещё раз даташит на тему таймеров и не нашёл у себя ничего криминального. Функции настройки таймера: uint32_t Timer_Get_SICmask(uint8_t TimerNum) { uint32_t SIC_IAR_Mask = 0xFFFFFFFF; SIC_IAR_Mask &= ~(0xF << (TimerNum << 2)); return SIC_IAR_Mask; } int8_t Timer7_Start(uint32_t FreqHz) { if (!FreqHz) return -1; // Выключаем таймер *pTIMER_DISABLE = TIMDIS7; // Настраиваем таймер *pTIMER7_CONFIG = OUT_DIS | PWM_OUT | PERIOD_CNT | IRQ_ENA; // Выход ШИМ отключен, режим PWM_OUT, счёт до периода, прерывание включено, сброс таймера в 1 (не в 0) // Ширина испульса ШИМ (в данном случае не важно) *pTIMER7_WIDTH = 1; // Период счёта таймера до обнуления с формированием запроса на прерывание *pTIMER7_PERIOD = (TMR_SCLK / FreqHz);// - 1; // Приоритет *pSIC_IAR4 = (*pSIC_IAR4 & Timer_Get_SICmask(7)) | P39_IVG(12); // Присваиваем вектор прерывания для IVG 14 REGISTER_ISR(12, ivg12_isr); // Включаем у SIC вход от периферии *pSIC_IMASK1 |= IRQ_TIMER7; // Обнуляем регистр-счётчик *pTIMER7_COUNTER = 0; // Запускаем таймер *pTIMER_ENABLE = TIMEN7; return 0; } Обработчик прерываний, общий для всех таймеров: ISR(ivg12_isr) { ssync(); uint32_t timer_status = *pTIMER_STATUS; // Снимаем флаги TIMILx и TOVF_ERRx с помощью W1C *pTIMER_STATUS = 0x00FF00FF; if (timer_status & TIMIL0) { } if (timer_status & TIMIL1) { } if (timer_status & TIMIL2) { } if (timer_status & TIMIL3) { } if (timer_status & TIMIL4) { } if (timer_status & TIMIL5) { } if (timer_status & TIMIL6) { } if (timer_status & TIMIL7) { } }
  13. Вы в правильном направлении движетесь. Любой переворот делается регистрами ILI (Бит AM и биты I/D регистра Entry Mode). Также посмотрите низкоуровневые процедуры работы с экраном (очистка экрана, закрашивание прямоугольника, вывод символа), в одном из китайских проектов видел зеркалирование на уровне этих процедур.
  14. Всё, что вы описали, взаимосвязано и причина ему - косяк в sys_arch.c. Решение я приводил здесь.
  15. У этого примера от ST несколько проблем, по которым есть информация в форуме. В вашем случае скорее всего теряются пакеты из-за косяков в порте Lwip для FreeRTOS.
  16. С получением точного времени у меня проблем нет. Проблема в коррекции субсекундного счётчика RTC, который пытается изменить процедура, приведённая выше. Судя по RTC->SSR, коррекция не проходит, не понятно почему. Делаю в соответствии с документом AN3371: Using the hardware real-time clock (RTC) in STM32 F0, F2, F3, F4 and L1 series of MCUs. Оказалось всё просто. После установки времени и даты в регистрах DR и TR, субсекундный счётчик сбрасывается и остаётся только вычислить и установить его новое значение. Рабочий вариант процедуры: void RTC_TimeSync(vTime DateTime) { uint32_t TimeReg, DateReg; // Преобразование времени в BCD TimeReg = ((DateTime.Sec % 10) & 0x0F); TimeReg |= (((DateTime.Sec / 10) & 0x07) << 4); TimeReg |= (((DateTime.Min % 10) & 0x0F) << 8); TimeReg |= (((DateTime.Min / 10) & 0x07) << 12); TimeReg |= (((DateTime.Hour % 10) & 0x0F) << 16); TimeReg |= (((DateTime.Hour / 10) & 0x03) << 20); // Преобразование даты в BCD DateReg = ((DateTime.Day % 10) & 0x0F); DateReg |= (((DateTime.Day / 10) & 0x03) << 4); DateReg |= (((DateTime.Month % 10) & 0x0F) << 8); DateReg |= (((DateTime.Month / 10) & 0x01) << 12); DateReg |= (((DateTime.Year % 10) & 0x0F) << 16); DateReg |= (((DateTime.Year / 10) & 0x0F) << 20); // Пишем ключи для доступа к регистрам RTC RTC->WPR = RTC_KEY1; RTC->WPR = RTC_KEY2; if (!(RTC->ISR & RTC_ISR_INITF)) // RTC не в режиме инициализации? { RTC->ISR = (uint32_t)RTC_INIT_MASK; // Переходим в режим инициализации RTC while (!(RTC->ISR & RTC_ISR_INITF)); // Ждём установки бита INIT в RTC->ISR } RTC->TR = TimeReg; // Пишем время в RTC RTC->DR = DateReg; // Пишем дату в RTC RTC->SHIFTR = (RTC_PREDIV_S - ((t100mks * 16384) / 10000) + 1) | RTC_SHIFTR_ADD1S; RTC->ISR &= ~RTC_ISR_INIT; // Выходим из режима инициализации RTC RTC->WPR = 0xFF; // Включаем защиту регистров RTC } Всем спасибо
  17. Необходимо реализовать синхронизацию даты/времени в устройстве с внешним хостом (по SNTP и другим протоколам) с точностью до сотен микросекунд. Задача, получившая эталонное время вызывает следующую функцию и передаёт ей структуру с временем: void RTC_TimeSync(vTime DateTime) { uint32_t TimeReg, DateReg; uint32_t SSR_old, SSR_new; // Преобразование времени в BCD TimeReg = ((DateTime.Sec % 10) & 0x0F); TimeReg |= (((DateTime.Sec / 10) & 0x07) << 4); TimeReg |= (((DateTime.Min % 10) & 0x0F) << 8); TimeReg |= (((DateTime.Min / 10) & 0x07) << 12); TimeReg |= (((DateTime.Hour % 10) & 0x0F) << 16); TimeReg |= (((DateTime.Hour / 10) & 0x03) << 20); // Преобразование даты в BCD DateReg = ((DateTime.Day % 10) & 0x0F); DateReg |= (((DateTime.Day / 10) & 0x03) << 4); DateReg |= (((DateTime.Month % 10) & 0x0F) << 8); DateReg |= (((DateTime.Month / 10) & 0x01) << 12); DateReg |= (((DateTime.Year % 10) & 0x0F) << 16); DateReg |= (((DateTime.Year / 10) & 0x0F) << 20); // Пишем ключи для доступа к регистрам RTC RTC->WPR = RTC_KEY1; RTC->WPR = RTC_KEY2; if (!(RTC->ISR & RTC_ISR_INITF)) // RTC не в режиме инициализации? { RTC->ISR = (uint32_t)RTC_INIT_MASK; // Переходим в режим инициализации RTC while (!(RTC->ISR & RTC_ISR_INITF)); // Ждём установки бита INIT в RTC->ISR } RTC->TR = TimeReg; // Пишем время в RTC RTC->DR = DateReg; // Пишем дату в RTC RTC->ISR &= ~RTC_ISR_INIT; // Выходим из режима инициализации RTC RTC->WPR = 0xFF; // Включаем защиту регистров RTC // Пишем ключи для доступа к регистрам RTC RTC->WPR = RTC_KEY1; RTC->WPR = RTC_KEY2; SSR_old = RTC->SSR; // Текущее значение синхронного счётчика SSR_new = RTC_PREDIV_S - ((DateTime.t100mks * 16384) / 10000); // Желаемое значение синхронного счётчика while (RTC->ISR & RTC_ISR_SHPF); if (SSR_new >= SSR_old) // К счётчику нужно прибавить (откат времени назад) RTC->SHIFTR = SSR_new - SSR_old; else // От счётчика нужно отнять (приращение времени) RTC->SHIFTR = ((16383 - SSR_old) + SSR_new) | RTC_SHIFTR_ADD1S; RTC->WPR = 0xFF; } RTC_PREDIV_S = 0x3FFF RTC_PREDIV_A = 0x01 Дата и время (до секунд) синхронизируется нормально, а вот коррекция доли секунд не отрабатывает. Вообще. Т.е. как будто я пишу только дату и время до секунд. Если заменить RTC простым счётом по таймеру, то синхронизация проходит верно и часы идут синхронно с удалёнными часами (т.е. пересчёт между форматами времени сделан верно).
  18. Если дёрнуть резет после установления напряжения питания, то старт был стабильным. Ну а отладчик как раз и дёргал резет.
  19. Стыдно признавать, но косяк действительно был в ноге BOOT0 Не был запаян резистор, подтягивающий её к земле, нога висела в воздухе. Сейчас всё стабильно стартует всегда :rolleyes:
  20. С векторами прерываний всё в порядке. В ходе экспериментов удалось выяснить следующее: - В случае когда процессор не стартует, генерация на кварце 25 МГц отсутствует. - При тактировании от HSI глюк повторяется аналогично тактованию от кварца. - Если при включении удерживать сброс при подаче питания и после этого отпустить сброс, то процессор стартует стабильно. Сброс после подачи питания приводит к нормальному старту процессора. - BOR включен, порог выставлен на 2,7В, при выставлении любых порогов или отключении BOR ситуация не меняется. Работу BOR проверили лабораторным БП - BOR срабатывает. Всё это при запитывании процессора от БП на той же плате (5В на LM2679 -> 3.3В на LM1085) - Под рукой есть плата Discovery с процессором STM32F407VG, при запитывании её от того же БП 3.3В (с платы устройства), процессор Discovery стартует стабильно. NRST у дискавери подключен аналогично. - Если запитывать процессор от лабораторного БП в обход БП на плате, то процессор стартует стабильно. Осциллограммы нарастания напряжения питания 3.3В (жёлтый) и уровня на ноге NRST (синий): От лабораторного БП: От нашего БП: Какие у кого соображения?
  21. Процессор STM32F407IGT6, ревизия Z. Проект STM32F4x7_ETH_LwIP_V1.0.0 с сайта stm, из которого выкинута работа с сетью, оставлена только задача мигания светодиодами. Коэффициенты PLL: M = 25, N = 336, P = 2, Q = 7. Кварц 25 МГц. При запуске под отладкой (jlink) процессор успешно стартует и начинает мигать светодиодами. При запуске не в отладке (при подаче питания) - процессор не стартует. Ножка PDR_ON подключена к Vdd. Куда копать?
  22. DHCP не совсем то что нужно. Устройства являются серверами, подключение к которым устанавливается по IP адресам сторонним софтом. Поэтому IP должны быть статическими. Вот только выставить верные при монтаже будут всё время забывать, поэтому нужен механизм который позволял бы найти все устройства в сети и выставить им статические IP.
  23. Имеем проект на FreeRTOS+LwIP. Необходимо реализовать механизм поиска устройств в локальной сети, когда IP-адреса устройств не известны и устройства могут иметь одинаковые IP-адреса по-умолчанию. Для поиска устройств планирую использовать протокол канального уровня (может быть LLDP или свой). Каков объём переделок в исходниках стека LwIP для реализации подобных не IP-протоколов? Может быть есть пример или хотя бы методика формирования не IP Ethernet-пакетов? Был бы признателен.
  24. Константы выбираете исходя из задач и нагрузки. Добиваетесь отсутствия ошибок выделения памяти и записи в очередь на максимальной загрузке. У меня так: #define TCPIP_MBOX_SIZE 150 #define DEFAULT_UDP_RECVMBOX_SIZE 20 #define DEFAULT_TCP_RECVMBOX_SIZE 70 #define DEFAULT_ACCEPTMBOX_SIZE 20 #define ETH_RXBUFNB 10 Попробуйте для начала заменить в функции sys_mbox_new *mbox = xQueueCreate( archMESG_QUEUE_LENGTH, sizeof( void * ) ); на *mbox = xQueueCreate( size, sizeof( void * ) ); и посмотрите как ведут себя счётчики переполнений. Убедитесь, что все очереди успешно создаются. Они отъедают кучу FreeRTOS, которой может не хватать.
  25. Разобрался! Баг 1: В sys_arch.c функция sys_mbox_t sys_mbox_new(int size) создавала всегда очередь длиной archMESG_QUEUE_LENGTH, вместо того чтобы создавать очередь передаваемого ей размера. Соответственно, все очереди были одинаковой длины (по-умолчанию 6), а настройки: #define TCPIP_MBOX_SIZE #define DEFAULT_UDP_RECVMBOX_SIZE #define DEFAULT_TCP_RECVMBOX_SIZE #define DEFAULT_ACCEPTMBOX_SIZE при создании очередей игнорировались. Баг 2: Исправление бага с отвалом пингов способом, который представлен на форуме st.com не совсем удачное. Если изменить ethernetif_input() в соответствии с их рекомендацией, то функция приёма пакетов (tcpip_input() для NO_SYS=0) вызывается примерно 270 раз на каждый пакет, что вызывает переполнение майлбоксов, используемых для передачи пакетов с задачи ethernetif_input в задачу tcpip_thread, что вызывает пропуски пакетов. Для борьбы с "отвалом пингов" использовал метод, рекомендованный здесь
×
×
  • Создать...