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

athlon64

Свой
  • Постов

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

  • Посещение

Сообщения, опубликованные athlon64


  1. Оказалось, что первое обращение по указателю 0x64000000 отрабатывалось, а последующие пропускались.

    Причина во включенном кэшировании записи в Cortex-M7 для адресного пространства 0x60000000 - 0x7FFFFFFF.

    Решение - включить ремап на адресное пространство 0xC0000000-0xDFFFFFFF, где кэширование записи отключено

    HAL_EnableFMCMemorySwapping();

     

  2. Коллеги, добрый день
    Использую 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 работает хорошо.

    Вроде всё просто, не понимаю что я мог упустить.

    Прошу вашей помощи

    Spoiler

    Запись в память:

    
    #define WriteComm(cmd)          *((uint16_t *)0x64000000) = cmd

    Инициализация FMC:

    
    void MX_FMC_Init(void)
    {
      FMC_NORSRAM_TimingTypeDef Timing = {0};
    
      // Perform the SRAM1 memory initialization sequence
      hsram1.Instance = FMC_NORSRAM_DEVICE;
      hsram1.Extended = FMC_NORSRAM_EXTENDED_DEVICE;
      // hsram1.Init
      hsram1.Init.NSBank = FMC_NORSRAM_BANK2;   // NE2
      hsram1.Init.DataAddressMux = FMC_DATA_ADDRESS_MUX_DISABLE;
      hsram1.Init.MemoryType = FMC_MEMORY_TYPE_SRAM;
      hsram1.Init.MemoryDataWidth = FMC_NORSRAM_MEM_BUS_WIDTH_16;
      hsram1.Init.BurstAccessMode = FMC_BURST_ACCESS_MODE_DISABLE;
      hsram1.Init.WaitSignalPolarity = FMC_WAIT_SIGNAL_POLARITY_LOW;
      hsram1.Init.WaitSignalActive = FMC_WAIT_TIMING_BEFORE_WS;
      hsram1.Init.WriteOperation = FMC_WRITE_OPERATION_ENABLE;
      hsram1.Init.WaitSignal = FMC_WAIT_SIGNAL_DISABLE;
      hsram1.Init.ExtendedMode = FMC_EXTENDED_MODE_DISABLE;
      hsram1.Init.AsynchronousWait = FMC_ASYNCHRONOUS_WAIT_DISABLE;
      hsram1.Init.WriteBurst = FMC_WRITE_BURST_DISABLE;
      hsram1.Init.ContinuousClock = FMC_CONTINUOUS_CLOCK_SYNC_ONLY;
      hsram1.Init.WriteFifo = FMC_WRITE_FIFO_DISABLE;
      hsram1.Init.PageSize = FMC_PAGE_SIZE_NONE;
    
      // Timing 
      Timing.AddressSetupTime = 2;
      Timing.AddressHoldTime = 0;
      Timing.DataSetupTime = 5;
      Timing.BusTurnAroundDuration = 0;
      Timing.CLKDivision = 0;
      Timing.DataLatency = 0;
      Timing.AccessMode = FMC_ACCESS_MODE_B;
    
      if (HAL_SRAM_Init(&hsram1, &Timing, NULL) != HAL_OK)
      {
        Error_Handler( );
      }
    }

     

  3. Добрый день

    Возможно кто-нибудь сталкивался с коммерческими САПР для проектирования печатных плат, доступ к которым можно было бы арендовать на время?

    Скажем на 6 или 12 месяцев.

     

    Было бы интересно оценить целесообразность покупки такой аренды для не сильно большого проекта.

     

  4. В общем в итоге имею вот что.

    После включения питания магнитолы (и атмеги) сразу попадаю в обработчик TWI с TWSR=0x00, переинициализирую TWI. Больше в обработчик не попадаю.

    Тем временем шина в магнитоле работает, TDA7563 включается.

     

    Напоминаю, что атмега и TDA7563 сидят на одной шине с одинаковыми i2c-slave адресами. Возможно с этим связана проблема, хотя, с моей точки зрения, так делать можно и если выдавать мастеру в данных только байты = 0xFF, то всё должно работать. Или я не прав?

     

    Ещё завтра попробую поднять частоту атмеги до 8МГц, сейчас 1МГц

  5. Попробуйте адрес 0x36, а то среди адресов I2C постоянная путаница - одни считают с младшим битом, а другие без него. Я постоянно накалываюсь - в даташите один адрес написан, а в действиельности его надо либо умножить на два, либо поделить.

    Т.е. попробуйте здесь:

    TWAR = 0x6C << 1;

    не делать сдвига влево.

    Спасибо за совет, это я попробовал сразу же :) тоже накалывался, и не раз

    но в даташите на атмегу и TDA всё однозначно написано, нужно именно TWAR = 0x6C << 1;

  6. В общем выяснилось, что была ошибка в обработчике прерывания от 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);		// Сброс флага прерывания.
    }

  7. Приветствую всех

    Делаю устройство на 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 атмеги нет.

  8. Излазил каталог Schroff и ещё нескольких производителей, не могу найти каркас который изображен на фото.

    В принципе сильно похож на euroPac PRO, но у europac высота бывает только 3 или 6 юнитов. Те модели, которые предлагаются в 2U, как правило не имеют рейку с отверстиями ближе к передней панели (нужно для крепления внутрь модулей). Также обычно на боковых стенках отсутствует направляющая для удобного монтажа/демонтажа в стойку.

    post-55882-1416840830_thumb.jpg

    post-55882-1416840843_thumb.jpg

    post-55882-1416840851_thumb.jpg

  9. Видимо пропуск прерывания происходит из-за того, что при обработке прерывания от одного таймера между строками

    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();
    }
    }
    

  10. Добрый день

    У меня в проекте на 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)
    {
    }
    }
    

  11. Почитал еще... Поменял биты. Картинка перевернулась.

    А вот текст почему-то оказался в той же ориентиции, что и раньше.

    В подпрограмме вывода текста не нашел ничего, влияющего на ориентацию.

     

    А библиотека у меня - ucGUI

     

    Вы в правильном направлении движетесь. Любой переворот делается регистрами ILI (Бит AM и биты I/D регистра Entry Mode).

    Также посмотрите низкоуровневые процедуры работы с экраном (очистка экрана, закрашивание прямоугольника, вывод символа), в одном из китайских проектов видел зеркалирование на уровне этих процедур.

  12. Здравствуйте, вообщем проблема такая, использую stm32f207+lwIP v1.4.0+FreeRTOS, среда IAR. Сам стек TCP/IP работает, только единственное что меня смущает, это ошибки в структуре lwip_stats->sys->mbox в поле err, число их становится все больше и больше, и за пару часов работы достигает 40000!!! При просмотре пакетов Wireshark'ом все нормально, изредка вылетают TCP_Retransmittion и TCP_ZeroWindow.

     

    Заранее спасибо.

    Всё, что вы описали, взаимосвязано и причина ему - косяк в sys_arch.c.

    Решение я приводил здесь.

  13. Смотрите в сторону PTP. Для начала гляньте AN3411 IEEE 1588 precision time protocol demonstration for STM32F107 connectivity line microcontroller. Конечно для достижения точности в наносекунды понадобится отдельный аппаратный TimeServer.

    С получением точного времени у меня проблем нет. Проблема в коррекции субсекундного счётчика 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
    }

    Всем спасибо

  14. Необходимо реализовать синхронизацию даты/времени в устройстве с внешним хостом (по 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 простым счётом по таймеру, то синхронизация проходит верно и часы идут синхронно с удалёнными часами (т.е. пересчёт между форматами времени сделан верно).

  15. А почему оно с отладчиком запускалсь, при плавающем буст0? Дллжно ведь было тоже глючить, или нет?

    Если дёрнуть резет после установления напряжения питания, то старт был стабильным.

    Ну а отладчик как раз и дёргал резет.

  16. А на BOOT0 случайно никаких резисторов с емкостями нет? Есть возможность после того как не стартанул подключиться отладчиком на всем скаку и посмотреть, куда его занесло - в загрузчик, в исключение или еще куда?

    Стыдно признавать, но косяк действительно был в ноге BOOT0 :biggrin:

    Не был запаян резистор, подтягивающий её к земле, нога висела в воздухе.

    Сейчас всё стабильно стартует всегда :rolleyes:

     

  17. С векторами прерываний всё в порядке.

    В ходе экспериментов удалось выяснить следующее:

    - В случае когда процессор не стартует, генерация на кварце 25 МГц отсутствует.

    - При тактировании от HSI глюк повторяется аналогично тактованию от кварца.

    - Если при включении удерживать сброс при подаче питания и после этого отпустить сброс, то процессор стартует стабильно. Сброс после подачи питания приводит к нормальному старту процессора.

    - BOR включен, порог выставлен на 2,7В, при выставлении любых порогов или отключении BOR ситуация не меняется. Работу BOR проверили лабораторным БП - BOR срабатывает.

    Всё это при запитывании процессора от БП на той же плате (5В на LM2679 -> 3.3В на LM1085)

    - Под рукой есть плата Discovery с процессором STM32F407VG, при запитывании её от того же БП 3.3В (с платы устройства), процессор Discovery стартует стабильно. NRST у дискавери подключен аналогично.

    - Если запитывать процессор от лабораторного БП в обход БП на плате, то процессор стартует стабильно.

     

    Осциллограммы нарастания напряжения питания 3.3В (жёлтый) и уровня на ноге NRST (синий):

    От лабораторного БП:

    post-55882-1352697820_thumb.jpg

    От нашего БП:

    post-55882-1352697863_thumb.jpg

     

    Какие у кого соображения?

  18. Процессор STM32F407IGT6, ревизия Z.

    Проект STM32F4x7_ETH_LwIP_V1.0.0 с сайта stm, из которого выкинута работа с сетью, оставлена только задача мигания светодиодами.

    Коэффициенты PLL: M = 25, N = 336, P = 2, Q = 7. Кварц 25 МГц.

     

    При запуске под отладкой (jlink) процессор успешно стартует и начинает мигать светодиодами.

    При запуске не в отладке (при подаче питания) - процессор не стартует.

    Ножка PDR_ON подключена к Vdd.

     

    Куда копать?

  19. А стандартный DHCP не?

    DHCP не совсем то что нужно.

    Устройства являются серверами, подключение к которым устанавливается по IP адресам сторонним софтом. Поэтому IP должны быть статическими.

    Вот только выставить верные при монтаже будут всё время забывать, поэтому нужен механизм который позволял бы найти все устройства в сети и выставить им статические IP.

  20. Имеем проект на FreeRTOS+LwIP.

    Необходимо реализовать механизм поиска устройств в локальной сети, когда IP-адреса устройств не известны и устройства могут иметь одинаковые IP-адреса по-умолчанию.

    Для поиска устройств планирую использовать протокол канального уровня (может быть LLDP или свой).

    Каков объём переделок в исходниках стека LwIP для реализации подобных не IP-протоколов?

    Может быть есть пример или хотя бы методика формирования не IP Ethernet-пакетов?

    Был бы признателен.

  21. Подскажите исходя из чего нужно задавать константы #define TCPIP_MBOX_SIZE, #define DEFAULT_UDP_RECVMBOX_SIZE, #define DEFAULT_TCP_RECVMBOX_SIZE, #define DEFAULT_ACCEPTMBOX_SIZE ? Или где можно про них почиать.

    В ST'шном примерах последние три констаны определены как 2000 O_O.

    У вас кстати ETH_RXBUFNB сколько стоит, 5? У меня до установки SYS_LIGHTWEIGHT_PROT 1, более менее стабильно работало только с ETH_RXBUFNB=1. Сейчас пробую с SYS_LIGHTWEIGHT_PROT 1 и ETH_RXBUFNB 5, на плате одновременно запущен TCP сервер и TCP клиент, работает это все уже часов 7, пока ничто не отвалилось но потихоньку накапливается lwip_stats.sys.mbox.err.

    Константы выбираете исходя из задач и нагрузки. Добиваетесь отсутствия ошибок выделения памяти и записи в очередь на максимальной загрузке. У меня так:

    #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, которой может не хватать.

  22. Разобрался!

     

    Баг 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, что вызывает пропуски пакетов.

    Для борьбы с "отвалом пингов" использовал метод, рекомендованный здесь

×
×
  • Создать...