Jump to content

    

Dimonira

Свой
  • Content Count

    432
  • Joined

  • Last visited

Community Reputation

0 Обычный

About Dimonira

  • Rank
    Местный

Recent Profile Visitors

1134 profile views
  1. STM32F777: Странное поведение NETCONN

    Кажется, я понял в чём дело. Подозреваю директиву #pragma pack(1) в своих заголовках. Исправил на пару #pragma pack(push, 1)/#pragma pack(pop), но проверить пока не могу - железо на работе. Не нашёл как удалить тему.
  2. Так везде в той или иной степени, всё зависит от запущенности (ака бедности) конторы.
  3. Я же не буду за свои покупать для работы анализатор. Итак уже натаскал на работу всякого, и тестер, и батарейки, и конвертер usb-ethernet, и планки памяти и т.д., уже всего и не упомню. Я сделал простейший костыль - чтение лишних битов. И этот костыль работает 100%. Ни одного сбоя не было, ибо если читается не то, что записывалось, то вызывается ErrorHandler с вечным циклом. В него ни разу процессор не заходил. Да и вопрос этот померк с свете другой проблемы (в соседней ветке).
  4. RDY не задействован, ибо в SPI интерфейсе отсутствует и Лог. анализатора нет.
  5. Столкнулся со странностью поведения NETCONN (но, может и сам где-то накосячил). Есть две задачи FreeRTOS, в каждой из которых создаётся свой NETCONN объект. В задаче, которая выполняется первой, странностей при создании NETCONN объекта нет. А во второй задаче есть: объект, возвращаемый netconn_new содержит некорректный адрес юниона pcb - он будто задом-наперёд. Я заходил пошагово в функцию netconn_new_with_proto_and_callback (она вызывается при netconn_new), в ней создаётся объект conn абсолютно нормальный: Но на следующем шаге, когда его адрес возвращается в точку вызова функции, отладчик показывает объект NETCONN с некорректным адресом pcb: В дальнейшем, естественно, при первой же попытке использовать, например, pUdpConn->pcb.udp->local_ip, процессор уходит в обработчик аппаратной ошибки. С чем может быть это связано? Стек задачи увеличивал - не помогло.
  6. Проверялось без FreeRTOS. SWV не включал. Тогда был J-LINK.
  7. Недавно я открыл для себя китайскую Trxcom. И, что самое приятное - низкие цены (от 60р) и наличие в российских конторах. Например, я покупал и для 100, и для гигабита в e-components.ru по 60-80р. 10/100: TRJ16664A28NL (62р) TRJ6011BBNL (94р) 1000: TRJG4806EBNL (75р)
  8. KSZ8863RLL

    Могу приложить свою схему для сравнения (самому сравнивать времени нет). Она работает с STM32F407, DHCP клиент получает адрес и т.п. С 8863 есть одна тонкость. У него нет регистра типа PHY SPECIAL CONTROL/STATUS REGISTER (0x1F) для получения текущего состояния скорости/дуплекса (как у LAN8742A, например). Думаю потому, что это свич. Если предположить, что контроллер у вас STM32 (вы не уточняли), то там стек протоколов заточен на этот регистр. Мне пришлось в Кубе поправить три значения в настройках, чтобы обмануть софт. Если у вас STM32, могу сказать какие. А ещё надо правильно задать адрес PHY. Опять же, в софте STM32 в инициализации делается программный сброс PHY, ожидание линка, получение состояния через интерфейс SMI, а в нём нужен корректный адрес PHY. Если это всё не получилось, то ничего дальше не будет.
  9. Хочу всё-таки уточнить: что именно мне было озвучено?
  10. Это всё общие слова. Здесь был конкретный трабл. Почему он возник так и осталось неизвестным.
  11. Странный вопрос... Это что-то вроде самокритики? Это к чему?
  12. Что хошь в FreeRTOS не получится. Вы вообще читали тему с начала?
  13. В итоге я сделал более-менее приемлемо - заменил три стандартные функции UART_RxISR_8BIT, UART_RxISR_16BIT и HAL_UART_Receive_IT на свои. Чтобы не было конфликта, сделал у них имена с суфиксом "_new": UART_RxISR_8BIT_new, UART_RxISR_16BIT_new, HAL_UART_Receive_IT_new. Я воспользовался полем дескриптора huart->RxXferSize, в которое HAL только записывает количество байтов для приёма, но нигде не использует. Сделал, чтобы при вызове HAL_UART_Receive_IT_new аргумент Size мог принимать значение 0, которое "сигнализирует" необходимость непрерывного приёма. Size как раз присваивается полю huart->RxXferSize, а если оно равно 0, то в UART_RxISR_8BIT_new и UART_RxISR_16BIT_new это используется как "сигнал", что приём надо продолжать, указатель в буфере и счётчик не менять, плюс надо вызвать HAL_UART_RxCpltCallback. То есть буфер при вызове HAL_UART_Receive_IT_new при Size = 0 может быть на одно слово (uint8_t или uint16_t). Если Size > 0, то всё будет работать по старому. Далее в main включаю новый заголовок и в дефолтовой задаче один раз делаю вызов HAL_UART_Receive_IT_new с аргументом Size = 0 и всё: void StartDefaultTask(void *argument) { /* init code for LWIP */ MX_LWIP_Init(); /* USER CODE BEGIN 5 */ logprintf("LWIP initialization done...\r\n"); // Запускаем приём UART по прерываниям for(int i = 0; i < NUMBER_OF_UARTS; i++) { if(uarts[i]) HAL_UART_Receive_IT_new(uarts[i], &rx_buf[i], 0); } logprintf("UART reception started...\r\n"); /* Infinite loop */ for(;;) { HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin); osDelay(500); } /* USER CODE END 5 */ } Функция обратного вызова остаётся в том же виде (без вызова HAL_UART_Receive_IT): void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { // Находим индекс UART int idx; for(idx = 0; idx < NUMBER_OF_UARTS; idx++) { if(uarts[idx] == huart) break; } // Готовим сообщение с принятым байтом MSG_UART_RX msg; msg.uart = idx; // индекс UART msg.byte = rx_buf[idx]; // принятый байт // Помещаем сообщение в очередь osMessageQueuePut(mid_RxQueue, &msg, 0, 0); } В файле stm32f7xx_it.c всё вернул взад как было (свой MY_UART_IRQHandler не нужен). Теперь всё работает как надо. И код HAL "не пострадал". Моё "дополнение" состоит из двух файлов. Исходник stm32f7xx_hal_uart_new.c: #include "stm32f7xx_hal_uart_new.h" #ifdef HAL_UART_MODULE_ENABLED /** * @brief RX interrrupt handler for 7 or 8 bits data word length . * @param huart UART handle. * @retval None */ static void UART_RxISR_8BIT_new(UART_HandleTypeDef *huart) { uint16_t uhMask = huart->Mask; uint16_t uhdata; /* Check that a Rx process is ongoing */ if (huart->RxState == HAL_UART_STATE_BUSY_RX) { uhdata = (uint16_t) READ_REG(huart->Instance->RDR); *huart->pRxBuffPtr = (uint8_t)(uhdata & (uint8_t)uhMask); if(huart->RxXferSize) { huart->pRxBuffPtr++; huart->RxXferCount--; } if (huart->RxXferCount == 0U) { /* Disable the UART Parity Error Interrupt and RXNE interrupts */ CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE)); /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */ CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); /* Rx process is completed, restore huart->RxState to Ready */ huart->RxState = HAL_UART_STATE_READY; /* Clear RxISR function pointer */ huart->RxISR = NULL; } if(huart->RxXferCount == 0U || !huart->RxXferSize) { #if (USE_HAL_UART_REGISTER_CALLBACKS == 1) /*Call registered Rx complete callback*/ huart->RxCpltCallback(huart); #else /*Call legacy weak Rx complete callback*/ HAL_UART_RxCpltCallback(huart); #endif /* USE_HAL_UART_REGISTER_CALLBACKS */ } } else { /* Clear RXNE interrupt flag */ __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST); } } /** * @brief RX interrrupt handler for 9 bits data word length . * @note Function is called under interruption only, once * interruptions have been enabled by HAL_UART_Receive_IT() * @param huart UART handle. * @retval None */ static void UART_RxISR_16BIT_new(UART_HandleTypeDef *huart) { uint16_t *tmp; uint16_t uhMask = huart->Mask; uint16_t uhdata; /* Check that a Rx process is ongoing */ if (huart->RxState == HAL_UART_STATE_BUSY_RX) { uhdata = (uint16_t) READ_REG(huart->Instance->RDR); tmp = (uint16_t *) huart->pRxBuffPtr ; *tmp = (uint16_t)(uhdata & uhMask); if(huart->RxXferSize) { huart->pRxBuffPtr += 2U; huart->RxXferCount--; } if (huart->RxXferCount == 0U) { /* Disable the UART Parity Error Interrupt and RXNE interrupt*/ CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE)); /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */ CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); /* Rx process is completed, restore huart->RxState to Ready */ huart->RxState = HAL_UART_STATE_READY; /* Clear RxISR function pointer */ huart->RxISR = NULL; } if(huart->RxXferCount == 0U || !huart->RxXferSize) { #if (USE_HAL_UART_REGISTER_CALLBACKS == 1) /*Call registered Rx complete callback*/ huart->RxCpltCallback(huart); #else /*Call legacy weak Rx complete callback*/ HAL_UART_RxCpltCallback(huart); #endif /* USE_HAL_UART_REGISTER_CALLBACKS */ } } else { /* Clear RXNE interrupt flag */ __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST); } } /** * @brief Receive an amount of data in interrupt mode. * @param huart UART handle. * @param pData Pointer to data buffer. If Size=0, then just one word buffer. * @param Size Amount of data to be received. If 0, then continuous reception of one word. * @retval HAL status */ HAL_StatusTypeDef HAL_UART_Receive_IT_new(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) { /* Check that a Rx process is not already ongoing */ if (huart->RxState == HAL_UART_STATE_READY) { if ((pData == NULL)) { return HAL_ERROR; } /* Process Locked */ __HAL_LOCK(huart); huart->pRxBuffPtr = pData; huart->RxXferSize = Size; huart->RxXferCount = !Size ? 1 : Size; huart->RxISR = NULL; /* Computation of UART mask to apply to RDR register */ UART_MASK_COMPUTATION(huart); huart->ErrorCode = HAL_UART_ERROR_NONE; huart->RxState = HAL_UART_STATE_BUSY_RX; /* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */ SET_BIT(huart->Instance->CR3, USART_CR3_EIE); /* Set the Rx ISR function pointer according to the data word length */ if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE)) { huart->RxISR = UART_RxISR_16BIT_new; } else { huart->RxISR = UART_RxISR_8BIT_new; } /* Process Unlocked */ __HAL_UNLOCK(huart); /* Enable the UART Parity Error interrupt and Data Register Not Empty interrupt */ SET_BIT(huart->Instance->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE); return HAL_OK; } else { return HAL_BUSY; } } #endif /* HAL_UART_MODULE_ENABLED */ И заголовок stm32f7xx_hal_uart_new.h: #ifndef STM32F7xx_HAL_UART_NEW_H #define STM32F7xx_HAL_UART_NEW_H #include "stm32f7xx_hal.h" #ifdef __cplusplus extern "C" { #endif /** * @brief Receive an amount of data in interrupt mode. * @param huart UART handle. * @param pData Pointer to data buffer. If Size=0, then just one word buffer. * @param Size Amount of data to be received. If 0, then continuous reception of one word. * @retval HAL status */ HAL_StatusTypeDef HAL_UART_Receive_IT_new(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size); #ifdef __cplusplus } #endif #endif /* STM32F7xx_HAL_UART_NEW_H */
  14. Можно конечно, но в каком месте забирать?
  15. Счётчик тогда уж увеличивать надо (при приёме он уменьшается). Но это не работает, ибо HAL_UART_RxCpltCallback никогда не вызовется, поскольку его вызов в UART_RxISR_8BIT случается только когда счётчик принятых байтов стал равен 0, а к моменту вызова "чёрное дело" по запрету прерываний и пр. уже случилось.