Jump to content

    

Ruslan1

Свой
  • Content Count

    2473
  • Joined

  • Last visited

Community Reputation

0 Обычный

About Ruslan1

  • Rank
    Гуру
  • Birthday 01/09/1973

Контакты

  • Сайт
    Array
  • ICQ
    Array

Информация

  • Город
    Array

Recent Profile Visitors

9679 profile views
  1. Кстати, почему бы не использовать для временных меток нестандартный, но вполне достаточный uint32_t ? На 130 лет хватит, начиная с 1970. Уже экономия в два раза, и переход от 64-битной арифметики на 32-битную. Upd: Хотя, если у Вас там возможно время до 1970, то не пойдет. Но может быть действительно можно остаться в рамках беззнакового 32 бит, пусть и нестандартно. При больших объемах хранения-траффика-вычислений такой подход вполне может иметь право быть.
  2. Поправка: Прерывание ETH_IRQHandler() вызывается постоянно. вызов xSemaphoreGiveFromISR() происходит постоянно. Но иногда (очень редко) происходит ассерт в queue.c во время этого вызова. Вызывающая функция: void ETH_IRQHandler(void) { portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; /* Frame received */ if (ETH_GetDMAFlagStatus(ETH_DMA_FLAG_R) == SET) { /* Give the semaphore to wakeup LwIP task */ xSemaphoreGiveFromISR(s_xSemaphore, &xHigherPriorityTaskWoken); } /* Clear the interrupt flags. */ /* Clear the Eth DMA Rx IT pending bits */ ETH_DMAClearITPendingBit(ETH_DMA_IT_R); ETH_DMAClearITPendingBit(ETH_DMA_IT_NIS); /* Switch tasks if necessary. */ if (xHigherPriorityTaskWoken != pdFALSE) { portEND_SWITCHING_ISR(xHigherPriorityTaskWoken); } } редко возникающий assert configASSERT( !( ( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) && ( pxQueue->pxMutexHolder != NULL ) ) ); внутри xSemaphoreGiveFromISR() : BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue, BaseType_t * const pxHigherPriorityTaskWoken ) { BaseType_t xReturn; UBaseType_t uxSavedInterruptStatus; Queue_t * const pxQueue = ( Queue_t * ) xQueue; /* Similar to xQueueGenericSendFromISR() but used with semaphores where the item size is 0. Don't directly wake a task that was blocked on a queue read, instead return a flag to say whether a context switch is required or not (i.e. has a task with a higher priority than us been woken by this post). */ configASSERT( pxQueue ); /* xQueueGenericSendFromISR() should be used instead of xQueueGiveFromISR() if the item size is not 0. */ configASSERT( pxQueue->uxItemSize == 0 ); /* Normally a mutex would not be given from an interrupt, and doing so is definitely wrong if there is a mutex holder as priority inheritance makes no sense for an interrupts, only tasks. */ configASSERT( !( ( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) && ( pxQueue->pxMutexHolder != NULL ) ) ); assert у меня такой: #define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); printf("FreeRTOS: Config Assert f:'%s',l:%d\r\n", (uint8_t *)__FILE__, __LINE__);for( ;; ); } #define taskDISABLE_INTERRUPTS() portDISABLE_INTERRUPTS() #define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI() static portFORCE_INLINE void vPortRaiseBASEPRI( void ) { uint32_t ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY; __asm { /* Set BASEPRI to the max syscall priority to effect a critical section. */ msr basepri, ulNewBASEPRI dsb isb } } После останова смотрю дебагером- все значения корректны, и результат проверки не может вызвать assert. Если принудительно перехожу на следующую строку в коде и выполняю дальше- все нормально выполняется, никаких проблем не вижу. Думал какое-то вложенное прерывание с некорректным приоритетом гадит в FreeRTOS- нет, все нормально и условия вызова не нарушены (проверил реальные регистры в NVIC после останова- что именно разрешено в системе и какие приоритеты имеет). Полтергейст какой-то. Upd: не понимаю. Такое ощущение, что где-то проблемы из-за использование не cоответствующих друг другу портов для FreeRTOS и lwIP, или внутренние проблемы. Думаю, нужно обновить мои версии 3-5 - летней давности на более новые. Может, это давно пофиксили, а я копаюсь в старье. Как я вижу, сейчас обработка очереди немного по другому сделана в новых версиях.
  3. несколько замечаний. Думаю, это касается многих кто использует LwIP 1.4.1. 1. существует многолетний баг во время создания мейлбоксов. Что бы ни задавали, всегда создается очередь дефолтовой длины. Это отлично описано athlon64 тут 2. порт freeRTOS для stm32: Если перейти на новый freeRTOS и не изменить прерывание (ETH_IRQHandler), то могут быть проблемы: в прерывании используется счетный семафор, а FreeRTOS имеет Assert на это дело. Нужно применять бинарный семафор. Описано тут. Пишут, что актуально для FreeRTOS после 8.1.2. Эта проблема с ассертом еще интересна вот чем: по езернету качаю нон-стоп (в основном передача). Но первый переход на строку вызова xSemaphoreGiveFromISR() в приведенном ниже коде произошел где-то через 7 часов после старта. То есть ассерта можно долго ждать и отлаживать непросто. До фиксации описанного в (1) бага я вообще этого ассерта не видел, даже не понимаю почему. void ETH_IRQHandler(void) { portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; /* Frame received */ if (ETH_GetDMAFlagStatus(ETH_DMA_FLAG_R) == SET) { /* Give the semaphore to wakeup LwIP task */ xSemaphoreGiveFromISR(s_xSemaphore, &xHigherPriorityTaskWoken); } /* Clear the interrupt flags. */ /* Clear the Eth DMA Rx IT pending bits */ ETH_DMAClearITPendingBit(ETH_DMA_IT_R); ETH_DMAClearITPendingBit(ETH_DMA_IT_NIS); /* Switch tasks if necessary. */ if (xHigherPriorityTaskWoken != pdFALSE) { portEND_SWITCHING_ISR(xHigherPriorityTaskWoken); } } Выводы из всего вышенаписанного: при изменении одного из компонентов нужно смотреть на совместимость. Если оно работает это еще не значит что оно совместимо. У меня, например, переход на более свежий freeRTOS 8.2.1 был сделан несколько лет назад, а несовместимость обнаружил только сейчас. ну и вызывает удивление многолетняя работа с багом #1... :)
  4. вот сфотографировал какие клипсы мне приехали. Есть черные и красные.
  5. Упс, да, извиняюсь. Но это не меняет главной идеи: использовать результат максимально возможной разрядности, и потом этот результат завернуть в 32 бита чем-то хорошим (вроде CRC32), а не просто отбрасывать старшие разряды. Да хотя бы еще раз перемножить перед отбрасыванием. Хорошо бы, конечно, посчитать, какая КС из придуманных на коленке будет лучшей по соотношению цена/качество. И тут для нестандартных велосипедов не все так просто- нужно еще придумать критерии оценки и сделать калькуляторы для этих критериев. Ну и сравнить хоть 2-3 метода между собой. Или хоть один метод на разных параметрах.
  6. Так условие-то: от перемены порядка обработки результат не меняется. А значит, сдвиги и прочие позиционно-зависимые стандартные вещи для "усиления КС" использовать нельзя. Тут только сложение и умножение остаются. Мне кажется, что умножение тут будет сильнее, чем сложение. Я бы предложил алгоритм: шаг#1: перемножить все 64 числа без отбрасывания старшей части. будет 32*64 = 2048 бит шаг#2: эти 2048 бит ужать до 32 бит (да хоть бы и через нормальную CRC32)
  7. Что значит "другие"? У меня именно такие и приехали, как на приведенной Вами картинке.
  8. Не хочу революцию. Пока что не готов менять FreeRTOS на другую, и даже FatFS на другое пока что. Мне достаточно вылизать свой код на предмет неиспользования f_puts и f_gets. Если идти дальше, то дополнительный кэш снизу может быть самым лучшим вариантом.
  9. Вы что-то делали в этом направлении? насколько трудоемко? У меня куча задач с доступом к диску (читают-пишут-создают-удаляют разные файлы), как-то не потянул я еще один уровень кэша добавлять снизу, а примеров в этом направлении не видел. Пока что ограничился кэшированием сверху- в задачах использую буферы по десятку килобайт, ну и только f_read и f_write, как выше написал. А наиболее агрессивные задачи на RAM диск пересадил.
  10. Про неочевидные вещи в FatFs. Кому-то это может и очевидно, но я сколько-то времени убил на осознание масштабов проблемы. Оставлю здесь, вдруг кому еще поможет. Про оптимизацию доступа к диску при многозадачности, когда много задач периодически лезут на диск по разным нуждам. Я тренировался на SD карточке, но касается любого носителя. Как бы Вы ни пытались оптимизировать доступ к диску, есть несколько внутренних функций, применение которых может очень сильно огорчить. Эти функции разбивают вроде бы одно цельное действие на гарантированно большое количество коротких доступов к диску. В результате происходит постоянная перезагрузка контента и внутренних кэшей SD карточки. Я про функции-обертки FatFs, которые внутри себя вызывают f_read() и f_write(). Но вот общаются они с диском уже маленькими порциями, так что любые потуги на организацию блочного чтения/записи в собственно драйвере нижнего уровня выгладят смешно и бесполезно. Например: f_puts() - обрабатывает данные маленькими порцийками, и передает в f_write() данные максимум по 62 байта. f_gets() - читает через f_read() по 1 или 2 или 3 или 4 байта, а не строками. Думаю, список таких функций-тормозов можно продолжить. Выход: делать все преобразования вне FatFs библиотек, и использовать только f_read() и f_write() для адекватного общения с железом носителя большими блоками.
  11. про U3Pro16 и софт DSView1.1.0 Поигрался с разными длинами буфера на реально интересных семплрейтах 125 и 250 MHz режим "Stream", 6 каналов. 125 MHz : без проблем максимальный доступный буфер может (около 132 секунды) 250 MHz: после 68-й секунды останавливается с ошибкой ("Data overflow" сообщение, говорит что полосы USB мало). режим "Stream", 12 каналов. 125 MHz: 78 секунд 250 MHz: 16 секунд Протоколы он может, вот ниже пример как я сейчас 4-байтовый протокол SD отлаживаю. режим "Stream". Захватываю 20 секунд на 125 МГц. Декодирование идет долго и не в реальном времени: занимает примерно в 50 раз больше времени, чем сам захват данных (20 секунд данных с семплрейтом 125 МГц). Ну это может комп виноват (Win7, Xeon E3, 3.2 GHz, но вот RAM только 8 GB). Но зато после декодирования одно удовольствие по данным бегать :)
  12. вот таки да, подпишусь под данным мнением. Очень важно вести статистику ошибок- по изменению процента ошибок принимать решение о нужности новых проверок. Еще проверяли осциллографом в точке приема: крутизну фронтов и помеховую ситуацию. По крутизне понятно какую скорость еще можно продавить, по помехам- вероятность возникновения ошибок. И вообще, RS-485 очень устойчив к многому, с практической точки зрения особо исследовать тут и не нужно ничего. Особый случай- это когда именно обследование линии заказано и оплачивается. Тогда чем больше графиков и брэндовых приборов, тем больше денег можно поиметь :)
  13. 1) Данная структура создается динамически с помощью malloc() для каждого снового соединения и удаляется, так что никаких постоянных известных адресов для указания в брейкпоинте просто нет. 2) даже если сделать статически(муторно, но теоретически можно), - я не могу поставить десятки брэйкпроинов на все нужные копии этой структуры в памяти - столько просто не поддерживается. Разве что новый процесс, периодически проверяющий эти адреса, и выдающий в лог тот момент, когда переменная испорчена. Может, что-то из этого вытащить можно. В-общем, путь с брэйкпоинтами мало подходит для динамически выделяемой памяти, да еще и если проблема редкая. Огроменное спасибо! Да, есть такая засада, у меня NETCONN и SOCKET одновременно разрешены. Буду думать и проверять. Про разные задачи- проверю снова. Очень даже возможно. 'LWIP_NETCONN_FULLDUPLEX' - вообще не вижу в моей версии LwIP (1.4.1). Это, думаю, уже в "двойке" добавили, Кстати, а имеет смысл на новый LwIP с моей 1.4.1 переходить? Каждые полгода опять начинаю думать про переход, особенно когда ковырять нужно как сейчас.
  14. Какую именно ситуацию Вы предлагаете отслеживать? У меня новые соединения создаются и закрываются чуть ли не ежесекундно, так что переменная записывается часто. А данная ошибка проявляется очень редко, не каждый день. И, к сожалению, не на столе. Я вот думаю, что еще можно в лог записать при возникновении этого ассерта, чтобы понять при анализе лога кем он был вызван. Проблема в том, что структура уже повреждена (иначе ассерта бы и не было), непонятно что писать. Разве что каждый случай записи логировать. Единственное что напрягает- это 'TCP_PCB': MEM TCP_PCB avail: 35 used: 34 max: 35 err: 0 Ошибки нет, но сколько я соединений разрешу ("the number of simulatenously active TCP connections."), столько система и занимает по максимуму. Похоже на утечку ресурса, но если связь оборвать (выдернуть LAN кабель)- то "used" возвращается в 0. Значит, зомби в системе нет, все под контролем, но все занято.
  15. Здравствуйте! Есть такая система: LwIP 1.4.1, FreeRTOS, на процессоре STM32F429 Иногда возникает ошибка "netconn_accept: invalid recvmbox", генерируемая функцией netconn_recv_data(), в строке: LWIP_ERROR("netconn_accept: invalid recvmbox", sys_mbox_valid(&conn->recvmbox), return ERR_CONN;); То есть указатель 'recvmbox' равен нулю. Но при этом не вижу ошибок в логах при создания самого recvmbox или conn (во время выделения памяти). Как такое может быть? Единственное что приходит на ум- это что идет обращение к уже закрытому соединению. Или есть еще варианты? (ну и конечно это может быть порча области памяти другой задачей, но этот вариант выходит за рамки задаваемого вопроса). Непонятно, как можно оследить откуда это было вызвано? Там работа через callback функции. Может происходит что-то вроде: соединение уже удалено, но callback сработал и вызвал обращение к уже несуществующему указателю? Можно ли как-то отследить кто такое сделал, или хоть понять чей 'recvmbox' испорчен? Или это при попытке закрыть уже закрытое соединение может быть? Какие логи включить в LwIP ? пока что включил так: #define LWIP_DEBUG 1 #define LWIP_STATS 1 #define LWIP_STATS_DISPLAY 1 #define MEM_STATS 1 #define MEMP_STATS 1 #define SYS_STATS 1 #define SOCKETS_DEBUG LWIP_DBG_ON #define MEMP_DEBUG LWIP_DBG_ON #define LWIP_PLATFORM_DIAG(x) do {printf x;} while(0) ну и логирую периодически текущее состояние через stats_display(). К сожалению, ошибка редкая, пока не не удалось ее получить во время логирование статистики. Вот и думаю, что еще сделать чтобы: 1) увидеть причину 2) может быть спровоцировать данную проблему чтобы она повторилась на столе, и спокойно отлаживать. Например, ужать какие-то параметры конфигурации, чтобы понять что именно этого ресурса не хватает. лог статистики из программы (но это без ошибки): может просто в настройках напортачил, вот они: #define SYS_LIGHTWEIGHT_PROT 1 #define ETHARP_TRUST_IP_MAC 0 #define IP_REASSEMBLY 0 #define IP_FRAG 0 #define ARP_QUEUEING 0 #define NO_SYS 0 #define MEM_ALIGNMENT 4 //#define MEMP_MEM_MALLOC 1 #define MEM_SIZE (115*1024) #define MEMP_SEPARATE_POOLS 1 #define MEMP_OVERFLOW_CHECK 1 #define MEMP_SANITY_CHECK 0 /* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application sends a lot of data out of ROM (or other static memory), this should be set high. */ #define MEMP_NUM_PBUF 12 /* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One per active UDP "connection". */ #define MEMP_NUM_UDP_PCB 12 /* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP connections. */ #define MEMP_NUM_TCP_PCB 35 /* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP connections. */ #define MEMP_NUM_TCP_PCB_LISTEN 7 /* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP segments. */ #define MEMP_NUM_TCP_SEG 66 /* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active timeouts. */ #define MEMP_NUM_SYS_TIMEOUT 10 #define MEMP_NUM_PPP_PCB 1 #define MEMP_NUM_NETCONN 26 /* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */ #define PBUF_POOL_SIZE 20 /* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */ #define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS+40+PBUF_LINK_HLEN) /** * MEMP_NUM_NETDB: the number of concurrently running lwip_addrinfo() calls * (before freeing the corresponding memory using lwip_freeaddrinfo()). */ #define MEMP_NUM_NETDB 10 #define MEMP_NUM_NETBUF 10 /* ---------- TCP options ---------- */ #define LWIP_TCP 1 #define TCP_TTL 255 /* Controls if TCP should queue segments that arrive out of order. Define to 0 if your device is low on memory. */ #define TCP_QUEUE_OOSEQ 1 /* TCP Maximum segment size. */ #define TCP_MSS (1500 - 40) /* TCP_MSS = (Ethernet MTU - IP header size - TCP header size) */ /* TCP sender buffer space (bytes). */ #define TCP_SND_BUF (8*TCP_MSS) /* TCP_SND_QUEUELEN: TCP sender buffer space (pbufs). This must be at least as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. */ #define TCP_SND_QUEUELEN (8* TCP_SND_BUF/TCP_MSS) /* TCP receive window. */ #define TCP_WND (4*TCP_MSS) /* ---------- ICMP options ---------- */ #define LWIP_ICMP 1 /* ---------- DHCP options ---------- */ /* Define LWIP_DHCP to 1 if you want DHCP configuration of interfaces. DHCP is not implemented in lwIP 0.5.1, however, so turning this on does currently not work. */ #define LWIP_DHCP 1 /* ---------- UDP options ---------- */ #define LWIP_UDP 1 #define UDP_TTL 255 #define LWIP_PROVIDE_ERRNO 1 /* -------------------------------------- ---------- Checksum options ---------- -------------------------------------- */ /* The STM32F4x7 allows computing and verifying the IP, UDP, TCP and ICMP checksums by hardware: - To use this feature let the following define uncommented. - To disable it and process by CPU comment the the checksum. */ //#define CHECKSUM_BY_HARDWARE /* ---------------------------------------------- ---------- Sequential layer options ---------- ---------------------------------------------- */ /** * LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c) */ #define LWIP_NETCONN 1 /* ------------------------------------ ---------- Socket options ---------- ------------------------------------ */ /** * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c) */ #define LWIP_SOCKET 1 /** * LWIP_TCP_KEEPALIVE==1: Enable TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT * options processing. Note that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set * in seconds. (does not require sockets.c, and will affect tcp.c) */ #define LWIP_TCP_KEEPALIVE 1 /** * LWIP_SO_RCVTIMEO==1: Enable receive timeout for sockets/netconns and * SO_RCVTIMEO processing. */ #define LWIP_SO_RCVTIMEO 1 //#define LWIP_PTP 1 /* ---------------------------------- ---------- DNS options ----------- ---------------------------------- */ /** * LWIP_DNS==1: Turn on DNS module. UDP must be available for DNS * transport. */ #ifndef LWIP_DNS #define LWIP_DNS 1 #endif /** DNS maximum number of entries to maintain locally. */ #define DNS_TABLE_SIZE 4 /** DNS maximum host name length supported in the name table. */ #define DNS_MAX_NAME_LENGTH 256 /** The maximum of DNS servers */ #define DNS_MAX_SERVERS 4 /** DNS do a name checking between the query and the response. */ #define DNS_DOES_NAME_CHECK 1 /** DNS message max. size. Default value is RFC compliant. */ #define DNS_MSG_SIZE 512 /** DNS_LOCAL_HOSTLIST: Implements a local host-to-address list. If enabled, * you have to define * #define DNS_LOCAL_HOSTLIST_INIT {{"host1", 0x123}, {"host2", 0x234}} * (an array of structs name/address, where address is an u32_t in network * byte order). * * Instead, you can also use an external function: * #define DNS_LOOKUP_LOCAL_EXTERN(x) extern u32_t my_lookup_function(const char *name) * that returns the IP address or INADDR_NONE if not found. */ #define DNS_LOCAL_HOSTLIST 0 /** If this is turned on, the local host-list can be dynamically changed * at runtime. */ #define DNS_LOCAL_HOSTLIST_IS_DYNAMIC 0 /* ----------------------------------- ---------- DEBUG options ---------- ----------------------------------- */ #define LWIP_DEBUG 1 #define LWIP_STATS 1 #define LWIP_STATS_DISPLAY 1 #define MEM_STATS 1 #define MEMP_STATS 1 #define SYS_STATS 1 #define SOCKETS_DEBUG LWIP_DBG_ON #define MEMP_DEBUG LWIP_DBG_ON #define LWIP_PLATFORM_DIAG(x) do {printf x;} while(0) /* --------------------------------- ---------- OS options ---------- --------------------------------- */ #define TCPIP_THREAD_STACKSIZE 16384 #define TCPIP_MBOX_SIZE 7 #define DEFAULT_UDP_RECVMBOX_SIZE 4000 #define DEFAULT_TCP_RECVMBOX_SIZE 4000 #define DEFAULT_ACCEPTMBOX_SIZE 4000 #define DEFAULT_THREAD_STACKSIZE 1000 #define TCPIP_THREAD_PRIO (configMAX_PRIORITIES - 1) #define PPP_SERIAL_PORT 0 #define PPP_SUPPORT 1 #define PPPOS_SUPPORT 1 #define PAP_SUPPORT 1 #define CHAP_SUPPORT 1 #define PPP_DEBUG 1 #define LWIP_PPP_API 1 #define LWIP_ARP 1 #define IP_FORWARD 1 #define LWIP_PTP 1 #define LWIP_COMPAT_MUTEX 1 #define TCP_OVERSIZE 1