![](https://electronix.ru/forum/uploads/set_resources_23/84c1e40ea0e759e3f1505eb1788ddf3c_pattern.png)
![](https://electronix.ru/forum/uploads/set_resources_23/84c1e40ea0e759e3f1505eb1788ddf3c_default_photo.png)
jeka
Свой-
Постов
467 -
Зарегистрирован
-
Посещение
-
CMTI, устойчивость к транзиентам
jeka опубликовал тема в Силовая Преобразовательная Техника
В микросхемах гальванической развязки есть параметр CMTI. И говорится в основном про влияние паразитной емкости между двумя частями. Хотя есть еще электромагнитные транзиенты, и подозреваю что резкое изменение потенциала может вносить спецэффекты в каком-то количестве. Хочу разобраться что будет если поставить микроконтроллер на фазу (для простоты допустим, имеющий автономное питание и со всех сторон экранированный, чтобы исключить емкостную связь и электромагнитную связь). Т.е. будет только резко меняться (с извесным slew rate) потенциал экранированной коробки с деталями (в точке подключения экрана). Резких мощных транзиентов тока вблизи нет. Будет ли влиять такое измение потенциала коробки на работу того что находится в коробке? У некоторых микроконтроллеров пишут "Not supposed to use in AC RC step-down powered or high EFT requirement applications". Имеется в виду что он не будет работать в незащищенной среде, или экранировка тоже не спасает? -
А трассировка момента стирания не смотрели на какой инструкции валится (если по одной ассемблерной инструкции трассировать)? И что в дампе флеш памяти после ресета? Возможно, стираете текущий исполняемый код. Не уверен что меняются местами регистры между собой при переключении банков.
-
Еще одна казалось бы мелочь. Вы сбрасываете источник прерывания так: TIM17->SR &= ~TIM_SR_CCxIF; Эта операция не атомарна и преобразовывается компилятором в 3 команды: чтение регистра, сброс бита, запись в регистр. Теперь подумайте, что произойдет если между чтением и записью таймер установит флаг какого-то другого события? Статус считан без установленного флага события, потом таймер выставил событие, и при записи флаг события сбросится. Чтобы этого не было сбрасывать события надо так: TIM17->SR = ~TIM_SR_CCxIF; Согласно даташиту, все единичные биты игнорируются, а там где ноль - будет сброс.
-
stm32h743, hal+lwip. Очень редко заклинивает передачу при интенсивном обмене. При заклиненной передаче вижу ситуацию: не очищен бит own в дескрипторе, освобождение которого ожидает драйвер (всего 4 дескриптора, остальные 3 дескриптора при этом очищены). Если ручками бит own очищаю, передачу расклинивает. К сожалению не посмотрел какой дескриптор ожидает периферия, жду следующего появления глюка. Кеш включен, MPU регионов с дескрипторами настроены по рекомендациям ST: // ======= memory policy (ethernet tx/rx descriptors) MPU->RNR = 11;// region number MPU->RBAR = 0x3004001B;// base address MPU->RASR = (0 << MPU_RASR_XN_Pos) |// DisableExec (1 << MPU_RASR_AP_Pos) |//AccessPermission (1 - privilegied only) ((0) << MPU_RASR_TEX_Pos) |//TypeExtField (0 << MPU_RASR_S_Pos) |//IsShareable (0 << MPU_RASR_C_Pos) |//IsCacheable (1 << MPU_RASR_B_Pos) |//IsBufferable (0 << MPU_RASR_SRD_Pos) |//SubRegionDisable (MPU_REGION_SIZE_512B<< MPU_RASR_SIZE_Pos)|//Size (1 << MPU_RASR_ENABLE_Pos);//Enable Кто-нибудь сталкивался с этим? Можно конечно механизм расклинивания дескрипторов для этой ситуации сделать, но хочется найти косяк и исправить по человечески.
-
Я получил без трансивера ~10(+-1)мбайт/сек записи, примерно столько же чтения. Без low-voltage трансивера это близко к пределу пропускной способности интерфейса sd карты. Загрузка cpu H743 порядка 10% получилась (реально меньше, ибо в загрузку еще получение по интерфейсу и предобработка данных включается). Без кеширования скорость записи была порядка 2-3МБ, но главная неприятность в том что при записи были регулярные фризы на время около 1 секунды (предполагаю, контроллер sd карты при многократной перезаписи одной области искусственно вносит задержку чтоб не истратить ресурс быстро). При кешировании ни одного фриза не заметил. В моем случае при потоковой записи такие фризы - очень неприятная штука.
-
Разобрался. Код этот рабочий, с размером блока напортачил. Плюс IDE в дампе EEPROM не обновляет дамп в реальном времени (обновляет только при запуске отладчика) и затирает EEPROM по умолчанию при программировании.
-
Не пойму в чем дело. Пытаюсь писать в eeprom, и никаких признаков что пишется не наблюдаю. В гугле есть аналогичный вопрос, без ответа торчит. void WriteFlash(const void* Src, void* Dst, int Len) { while (NVMCTRL.STATUS & 3) {}; uint8_t* SrcB = (uint8_t*)Src; volatile uint8_t* DstB = (uint8_t*)Dst; CPU_CCP=0x9D;// unlock for next 4 cycles. ints skipped for 4 cycles NVMCTRL.CTRLA=NVMCTRL_CMD_PAGEBUFCLR_gc; while (NVMCTRL.STATUS & 3) {}; for (int i=0; i<Len; i++) { *(DstB++) = *(SrcB++); } CPU_CCP=0x9D;// unlock for next 4 cycles. ints skipped for 4 cycles NVMCTRL.CTRLA=NVMCTRL_CMD_PAGEERASEWRITE_gc; while (NVMCTRL.STATUS & 3) {}; } #define SETTINGS_ADDR 0x1400 WriteFlash ((void*)&settings, (void*)SETTINGS_ADDR, sizeof (struct SETTINGS)); // пробовал и штатную функцию вызывать. эффект аналогичный: #include <avr/eeprom.h> eeprom_write_block ((void*)&settings, (void*)0/*SETTINGS_ADDR*/, sizeof (struct SETTINGS)); смотрел дамп в mplab x 5.50. везде ff ff...
-
Увы, это не так. Совсем. Во-первых, модуль кеширования как раз занимается всем этим: и группировкой секторов в блоки, и умным префетчем, и отсеканием ненужных/пустых операций, и выравниванием операций по границе. Просто увеличив размер сектора до 4к мы как минимум половину из этих проблем не решаем, ибо я детально изучал какие обращения делает fatfs на каких операциях, там много избыточных обращений, которые можно вылечить либо серьезным усложнением самого fatfs, либо на порядок более простым модулем кеширования. К тому же, размер блока SD карты обычно больше 4к, со всеми вытекающими. А при работающем кеше 4к блоки у fatfs не имеют никакого практического смысла. Еще приятный бонус кеширования - можно операции чтения-записи к fatfs делать любыми удобными кусками, хоть по 5 байт, можно бустро и часто открывать-закрывать файлы без перечитывания цепочек fat и каталогов. Модуль кеширования всё это выстраивает и оптимизирует.
-
Я с SD карточкой тоже боролся. Тоже смотрел в сторону увеличить блок данных (точнее, почему блок указан длинный, но пишется-читается все равно по 512 байт). В процессе разбора кода понял что лучше сделать модуль кеширования. В первую очередь чтобы ресурс флешки продлить - fatfs бестолково пишет некоторые сектора по многу раз в одно и то же место. В итоге немного допилил сам fatfs, ибо модулю кеширования для правильного выбора метода кеширования нужно знать какой это сектор - fat, каталога или кластер данных. Т.е. при кешировании данных модуль кеширования использует разные стратегии кеширования для кластеров, fat и каталогов. Ну и умеет буферизировать чтение и запись.
-
После патча косяки исчезли. Вот подправленный варинат: static ETH_BufferTypeDef RxBuff[ETH_RX_DESC_CNT];// вынес в статику, чтоб при каждом пакете не инициализировать их заново. static struct pbuf * low_level_input(struct netif *netif) { struct pbuf *p = NULL; uint32_t framelength = 0; struct pbuf_custom* custom_pbuf; if (HAL_ETH_GetRxDataBuffer(&heth, RxBuff) == HAL_OK) { HAL_ETH_GetRxDataLength(&heth, &framelength); #if !defined(DUAL_CORE) || defined(CORE_CM7) // SCB_InvalidateDCache_by_Addr((uint32_t *)RxBuff->buffer, framelength); __DSB();// если кеш принимаемых пакетов отключен #endif lan_stats.rx_frames++; custom_pbuf = (struct pbuf_custom*)LWIP_MEMPOOL_ALLOC(RX_POOL); if(custom_pbuf != NULL) { custom_pbuf->custom_free_function = pbuf_free_custom; p = pbuf_alloced_custom(PBUF_RAW, framelength, PBUF_REF, custom_pbuf, RxBuff->buffer, framelength); } } return p; } extern SemaphoreHandle_t ipSemaphore; void ethernetif_input(void* argument) { struct pbuf *p; struct netif *netif = (struct netif *) argument; memset(RxBuff, 0 , ETH_RX_DESC_CNT*sizeof(ETH_BufferTypeDef)); for(int i = 0; i < ETH_RX_DESC_CNT -1; i++) RxBuff[i].next=&RxBuff[i+1]; while (ipSemaphore==NULL) osDelay(1); for( ;; ) { if (osSemaphoreAcquire(RxPktSemaphore, TIME_WAITING_FOR_INPUT) == osOK) { do { p = low_level_input( netif ); if (p != NULL) { // if (netif->input( p, netif) != ERR_OK ) if( xSemaphoreTake( ipSemaphore, ( TickType_t ) 0 ) ) { ethernet_input(p, netif); xSemaphoreGive( ipSemaphore ); } else pbuf_free(p); /* Build Rx descriptor to be ready for next data reception */ HAL_ETH_BuildRxDescriptors(&heth); } } while(p!=NULL); } } } И в tcpip.c семафор вставил: SemaphoreHandle_t ipSemaphore = NULL; static void tcpip_thread(void *arg) { struct tcpip_msg *msg; LWIP_UNUSED_ARG(arg); ipSemaphore = xSemaphoreCreateMutex(); xSemaphoreGive( ipSemaphore ); LWIP_MARK_TCPIP_THREAD(); LOCK_TCPIP_CORE(); if (tcpip_init_done != NULL) { tcpip_init_done(tcpip_init_done_arg); } while (1) { /* MAIN Loop */ LWIP_TCPIP_THREAD_ALIVE(); /* wait for a message, timeouts are processed while waiting */ TCPIP_MBOX_FETCH(&tcpip_mbox, (void **)&msg); if (msg == NULL) { LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: NULL\n")); LWIP_ASSERT("tcpip_thread: invalid message", 0); continue; } if( xSemaphoreTake( ipSemaphore, ( TickType_t ) 0 ) ) { tcpip_thread_handle_msg(msg); xSemaphoreGive( ipSemaphore ); } } }
-
Поразбирался. Самое веселое, что куда ни ставь HAL_ETH_BuildRxDescriptors, глюк не исчезает по банальной причине - пакет обрабатывается в другом потоке... Пришел пакет -> вызвалось Ethernet IRQ -> RxPktSemaphore -> завершение IRQ далее отрабатывает Ethif task: ethernetif_input -> tcpip_inpkt -> sys_mbox_trypost -> osMessageQueuePut -> xQueueSendToBack -> и в конце вызывает HAL_ETH_BuildRxDescriptors. Причем если вызов HAL_ETH_BuildRxDescriptors перенести в tcpip_thread, HAL перестанет сдвигать буфера и будет бесконечно один и тот же пакет пытаться отправить. далее, всё это принимает поток tcpip_thread. И в ней уже обрабатывается пакет, который был освобожден предыдущим потоком, со всеми вытекающими: tcpip_thread -> ethernet_input Вообщем, сделали крайне бестолково. Думаю, весь Ethif task надо убирать ибо он не нужен, а пакет из ethernetif_input сразу отдавать на обработку в ethernet_input.
-
Как раз хотелось бы дескрипторы поменьше, например 128 байт, но общий объем буферов около 20кб. Иначе при маленьких пакетах и больших буферах эффективность использования RAM низкая, а packet rate может быть весьма высокий. И получается, если система задумалась при обработке жирного пакета, на буферизацию мелких пакетов может памяти не хватить (что собственно и происходит на практике). Сейчас смотрю реализацию езернета в порте микропитона под STM... Код явно в разы шустрей чем hal от stm. Видимо придется взять его за основу и немного доработать, ибо он на мелкие дескрипторы не заточен. Потрассировал HAL - честно разочаровывают программисты от ST. такие жирные функции крутить на каждом пакете, которые по факту ничего не делают. Вероятно, у Вас в поллинг режиме езернет работает. Мне же нужно с IRQ и RTOS.
-
Еще не понял. HAL_ETH_GetRxDataLength(&heth, &framelength); - это размер всего пакета же, а не одного куска в дескрипторе? т.е. далее по тексту сброс DCACHE подразумевает целый пакет одним куском. Но... ведь пакет может быть в нескольких дескрипторах и не подряд идущих (переход по кругу от последнего буфера к первому), и получается хвост может потерять, если пакет не влезает в один дескриптор?
-
При работе езернета натолкнулся на интересный глюк - содержимое пакета во время обработки может перезаписаться (на другой пакет). Причем долго работало нормально, стало проявляться только когда много коротких пакетов после задержки в роутере пачкой выплёвываются. Стал копать. Смотрю, куб из коробки генерирует такой вот код (специально обновил куб, свежий то же самое генерит): static struct pbuf * low_level_input(struct netif *netif) { struct pbuf *p = NULL; uint32_t framelength = 0, i = 0; struct pbuf_custom* custom_pbuf; ETH_BufferTypeDef RxBuff[ETH_RX_DESC_CNT]; memset(RxBuff, 0 , ETH_RX_DESC_CNT*sizeof(ETH_BufferTypeDef)); for(i = 0; i < ETH_RX_DESC_CNT -1; i++) { RxBuff[i].next=&RxBuff[i+1]; } if (HAL_ETH_GetRxDataBuffer(&heth, RxBuff) == HAL_OK) { HAL_ETH_GetRxDataLength(&heth, &framelength); HAL_ETH_BuildRxDescriptors(&heth); #if !defined(DUAL_CORE) || defined(CORE_CM7) /* Invalidate data cache for ETH Rx Buffers */ SCB_InvalidateDCache_by_Addr((uint32_t *)RxBuff->buffer, framelength); #endif lan_stats.rx_frames++; custom_pbuf = (struct pbuf_custom*)LWIP_MEMPOOL_ALLOC(RX_POOL); if(custom_pbuf != NULL) { custom_pbuf->custom_free_function = pbuf_free_custom; p = pbuf_alloced_custom(PBUF_RAW, framelength, PBUF_REF, custom_pbuf, RxBuff->buffer, framelength); } } return p; } забавно, что HAL_ETH_BuildRxDescriptors (как я понял это функция, которая помечает буфера приема как "свободно") вызывается не дожидаясь обработки пакета (которая в традиционно в процессе RTOS крутится). Подебажил - действительно, после вызова HAL_ETH_BuildRxDescriptors буфер перезаписывается свежими пакетами. Вот думаю, что разработчики имели в виду написав так... и как проще исправить.
-
Программист GUI под STM32
jeka ответил jeka тема в Предлагаю работу
Да, lvgl уже подключил. На первый взгляд очень понравилось - документация адекватная, архитетура сделана по уму. openvg интересная наработка, будет время попробую. Откликов как-то не густо. Сложностью испугал или ценник не озвучил? платить готовы достойно, главное получить результат. Лучше конечно в перспективе рассматривать как длительное сотрудничество, а не разовую задачу.