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

Прием данных с WIFI модуля блокирует получение данных по UART

Чип STM32L475VC + ISM43362 WIFI Module.

Настраиваю модуль, подключаюсь к AP, запускаю сервер.

Spoiler

 if(ISM43362_Init() == WIFI_STATUS_OK)
    {
        USART_SendString(SYS_USART, "WIFI INIT OK\r");
        if(WIFI_GetMAC_Address(mac_addr) == WIFI_STATUS_OK)
        {
            USART_SendString(SYS_USART, "MAC ADDRESS ");
            USART_SendHex(SYS_USART, mac_addr[0],0);
            USART_SendString(SYS_USART, ":");
            USART_SendHex(SYS_USART, mac_addr[1],0);
            USART_SendString(SYS_USART, ":");
            USART_SendHex(SYS_USART, mac_addr[2],0);
            USART_SendString(SYS_USART, ":");
            USART_SendHex(SYS_USART, mac_addr[3],0);
            USART_SendString(SYS_USART, ":");
            USART_SendHex(SYS_USART, mac_addr[4],0);
            USART_SendString(SYS_USART, ":");
            USART_SendHex(SYS_USART, mac_addr[5],1);
        }
    }
    else
      USART_SendString(SYS_USART, "WIFI INIT ERROR\r");

if( WIFI_Connect(SSID, PASSWORD, WIFI_ECN_WPA2_PSK) == WIFI_STATUS_OK)
    {
        if(WIFI_GetIP_Address(ip_addr) == WIFI_STATUS_OK)
        {
            USART_SendString(SYS_USART, "Connected: got IP Address ");
            USART_SendInt(SYS_USART, ip_addr[0], 0);
            USART_SendString(SYS_USART, ".");
            USART_SendInt(SYS_USART, ip_addr[1], 0);
            USART_SendString(SYS_USART, ".");
            USART_SendInt(SYS_USART, ip_addr[2], 0);
            USART_SendString(SYS_USART, ".");
            USART_SendInt(SYS_USART, ip_addr[3], 1);
        }
        else
        {
	   USART_SendString(SYS_USART , "ERROR: CANNOT get IP address\r");
        }
    }

if (WIFI_StartServer(SOCKET, WIFI_TCP_PROTOCOL, 1, "", PORT) == WIFI_STATUS_OK)
        USART_SendString(SYS_USART, "Start server - SUCCESS\r");
    else
        USART_SendString(SYS_USART, "Start server - ERROR\r");

 

все проходит на ура

Quote

WIFI INIT OK
MAC ADDRESS C4:7F:51:7:B5:A5
Connected: got IP Address 172.16.1.120
Start server - SUCCESS

 


в мэйн запускаю обработку комманды пользователя с терминала

while (1)
{ 
      
    if (uart4_rx_ready)
    {
       uart4_rx_ready = 0;
            
       PARSER_ParseCommand(uart4_rx_buf);
    }     
      
}

все отлично. команды принимаются.

добавляю получение данных с модуля

while (1)
{      
    if (uart4_rx_ready)
    {
        uart4_rx_ready = 0;
            
        PARSER_ParseCommand(uart4_rx_buf);      
    }

    if (WIFI_STATUS_OK == WIFI_ReceiveData(SOCKET, udp_rx_buf, 1000, &udp_rx_len, 0 ))
    {
        if (udp_rx_len > 0)
          USART_SendInt(SYS_USART, udp_rx_len, 1);
    }
       
}

и тут прием с UART ломается. по чару принимает, но если послать весь стринг то принимает первый чар и подымается флаг ORE: Overrun error.

я думал  WIFI_ReceiveData блокирующий, но если ставлю точку останова в любой строке кода все бежит без задержек.

в чем может быть проблема?

Изменено пользователем jenya7

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, jenya7 сказал:

я думал  WIFI_ReceiveData блокирующий, но если ставлю точку останова в любой строке кода все бежит без задержек.

Ничего не понятно, но очень интересно, продолжайте...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

ну скажем так, нечего блокировать. никаких данных не приходит он сразу выходит с DEBUG("setting socket for read failed\n");

есть проекты с более массивным чтением где я в цикле вычитываю массивы данных и ничего прием по UART работает чётко.

обращение к модулю по SPI. чары с  UART я собираю в массив по прерыванию. ну пусть он вычитывает по SPI буфер, я приму свою команду и подниму флаг.

 

ORE: Overrun error - это пришёл новый чар а я не успел считать старый? как такое может быть, я в прерывании сразу его считываю. что может блокировать прерывание?

Изменено пользователем jenya7

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 часа назад, jenya7 сказал:

Overrun error - это пришёл новый чар а я не успел считать старый?

Да.

 

3 часа назад, jenya7 сказал:

что может блокировать прерывание?

Очевидно что-то в вашей программе, которую никто, кроме вас не видит..

3 часа назад, jenya7 сказал:

обращение к модулю по SPI. чары с  UART я собираю в массив по прерыванию. ну пусть он вычитывает по SPI буфер, я приму свою команду и подниму флаг.

Причем тут уарт и спи? СПИ тоже по прерываниям работает? Тогда может там и "давит"...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 6/16/2021 at 5:18 PM, jenya7 said:

ORE: Overrun error - это пришёл новый чар а я не успел считать старый? как такое может быть, я в прерывании сразу его считываю. что может блокировать прерывание?

 

Как я понял, есть два источника данных. Оба работают по прерыванию. Один из источников переполняет буфер приема.

Может с приоритетами прерываний поиграть?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 hour ago, KnightIgor said:

Как я понял, есть два источника данных. Оба работают по прерыванию. Один из источников переполняет буфер приема.

Может с приоритетами прерываний поиграть?

если убрать

if (WIFI_STATUS_OK == WIFI_ReceiveData(SOCKET, udp_rx_buf, 1000, &udp_rx_len, 0 ))
    {
        if (udp_rx_len > 0)
          USART_SendInt(SYS_USART, udp_rx_len, 1);
    }
       

то все нормально.

наверное обращение к неоткрытому сокету делает проблему. правда как это связано с UART я так и не понял.

Изменено пользователем jenya7

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

20 minutes ago, jenya7 said:

если убрать


if (WIFI_STATUS_OK == WIFI_ReceiveData(SOCKET, udp_rx_buf, 1000, &udp_rx_len, 0 ))
    {
        if (udp_rx_len > 0)
          USART_SendInt(SYS_USART, udp_rx_len, 1);
    }
       

то все нормально.

наверное обращение к неоткрытому сокету делает проблему. правда как это связано с UART я так и не понял.

 

1. Кто писал  _ReceiveData? Может там есть код, который запрещает прерывания на время?

2. _SendInt посылает через прерывания? Если да, то может приоритет этого прерывания выше приема UART, да еще в прерывании достаточно длительная предобработка ведется? Попробуйте закомментировать именно _SendInt, а если есть полный контроль над этой функцией, попробовать передавать с помощью DMA.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 hour ago, KnightIgor said:

1. Кто писал  _ReceiveData? Может там есть код, который запрещает прерывания на время?

2. _SendInt посылает через прерывания? Если да, то может приоритет этого прерывания выше приема UART, да еще в прерывании достаточно длительная предобработка ведется? Попробуйте закомментировать именно _SendInt, а если есть полный контроль над этой функцией, попробовать передавать с помощью DMA.

ReceiveData не трогает прерывания

Spoiler

WIFI_Status_t WIFI_ReceiveData(uint8_t socket, uint8_t *pdata, uint16_t Reqlen, uint16_t *RcvDatalen, uint32_t Timeout)
{
  WIFI_Status_t ret = WIFI_STATUS_ERROR;
  EsWifiObj.Timeout = Timeout;  //1000
  if(ES_WIFI_ReceiveData(&EsWifiObj, socket, pdata, Reqlen, RcvDatalen, Timeout) == ES_WIFI_STATUS_OK) 
  //if(ES_WIFI_AltReceiveData(&EsWifiObj, socket, pdata, Reqlen, RcvDatalen, Timeout) == ES_WIFI_STATUS_OK)  
  {
    ret = WIFI_STATUS_OK;
  }
  return ret;
}

ES_WIFI_Status_t ES_WIFI_ReceiveData(ES_WIFIObject_t *Obj, uint8_t Socket, uint8_t *pdata, uint16_t Reqlen, uint16_t *Receivedlen, uint32_t Timeout)
{
  uint32_t wkgTimeOut;

  ES_WIFI_Status_t ret = ES_WIFI_STATUS_ERROR;

  if (Timeout == 0)
  {
    wkgTimeOut = NET_DEFAULT_NOBLOCKING_READ_TIMEOUT;
  }
  else
  {
    wkgTimeOut = Timeout;
  }

  LOCK_WIFI();

  if(Reqlen <= ES_WIFI_PAYLOAD_SIZE )
  {
    sprintf((char*)Obj->CmdData,"P0=%d\r", Socket);
    ret = AT_ExecuteCommand(Obj, Obj->CmdData, Obj->CmdData);

    if(ret == ES_WIFI_STATUS_OK)
    {
      sprintf((char*)Obj->CmdData,"R1=%d\r", Reqlen);
      ret = AT_ExecuteCommand(Obj, Obj->CmdData, Obj->CmdData);
      if(ret == ES_WIFI_STATUS_OK)
      {
        sprintf((char*)Obj->CmdData,"R2=%lu\r", wkgTimeOut);
        ret = AT_ExecuteCommand(Obj, Obj->CmdData, Obj->CmdData);
        if(ret == ES_WIFI_STATUS_OK)
        {
          sprintf((char*)Obj->CmdData,"R0\r");
          ret = AT_RequestReceiveData(Obj, Obj->CmdData, (char *)pdata, Reqlen, Receivedlen);
          if (ret != ES_WIFI_STATUS_OK)
          {
            DEBUG("AT_RequestReceiveData  failed\n");
          }
        }
        else
        {
         DEBUG("setting timeout failed\n");
        }
      }
      else
      {
        DEBUG("setting requested len failed\n");
        *Receivedlen = 0;
      }
    }
    else
    {
      DEBUG("setting socket for read failed\n");
      issue15++;
    }
  }
  UNLOCK_WIFI();
  return ret;
}

 

LOCK_WIFI() пустышка.

до USART_SendInt я не дохожу так как условие if (WIFI_STATUS_OK == WIFI_ReceiveData(SOCKET, udp_rx_buf, 1000, &udp_rx_len, 1000 )) не выполняется.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

22 minutes ago, jenya7 said:

ReceiveData не трогает прерывания

  Reveal hidden contents


WIFI_Status_t WIFI_ReceiveData(uint8_t socket, uint8_t *pdata, uint16_t Reqlen, uint16_t *RcvDatalen, uint32_t Timeout)
{
  WIFI_Status_t ret = WIFI_STATUS_ERROR;
  EsWifiObj.Timeout = Timeout;  //1000
  if(ES_WIFI_ReceiveData(&EsWifiObj, socket, pdata, Reqlen, RcvDatalen, Timeout) == ES_WIFI_STATUS_OK) 
  //if(ES_WIFI_AltReceiveData(&EsWifiObj, socket, pdata, Reqlen, RcvDatalen, Timeout) == ES_WIFI_STATUS_OK)  
  {
    ret = WIFI_STATUS_OK;
  }
  return ret;
}

ES_WIFI_Status_t ES_WIFI_ReceiveData(ES_WIFIObject_t *Obj, uint8_t Socket, uint8_t *pdata, uint16_t Reqlen, uint16_t *Receivedlen, uint32_t Timeout)
{
  uint32_t wkgTimeOut;

  ES_WIFI_Status_t ret = ES_WIFI_STATUS_ERROR;

  if (Timeout == 0)
  {
    wkgTimeOut = NET_DEFAULT_NOBLOCKING_READ_TIMEOUT;
  }
  else
  {
    wkgTimeOut = Timeout;
  }

  LOCK_WIFI();

  if(Reqlen <= ES_WIFI_PAYLOAD_SIZE )
  {
    sprintf((char*)Obj->CmdData,"P0=%d\r", Socket);
    ret = AT_ExecuteCommand(Obj, Obj->CmdData, Obj->CmdData);

    if(ret == ES_WIFI_STATUS_OK)
    {
      sprintf((char*)Obj->CmdData,"R1=%d\r", Reqlen);
      ret = AT_ExecuteCommand(Obj, Obj->CmdData, Obj->CmdData);
      if(ret == ES_WIFI_STATUS_OK)
      {
        sprintf((char*)Obj->CmdData,"R2=%lu\r", wkgTimeOut);
        ret = AT_ExecuteCommand(Obj, Obj->CmdData, Obj->CmdData);
        if(ret == ES_WIFI_STATUS_OK)
        {
          sprintf((char*)Obj->CmdData,"R0\r");
          ret = AT_RequestReceiveData(Obj, Obj->CmdData, (char *)pdata, Reqlen, Receivedlen);
          if (ret != ES_WIFI_STATUS_OK)
          {
            DEBUG("AT_RequestReceiveData  failed\n");
          }
        }
        else
        {
         DEBUG("setting timeout failed\n");
        }
      }
      else
      {
        DEBUG("setting requested len failed\n");
        *Receivedlen = 0;
      }
    }
    else
    {
      DEBUG("setting socket for read failed\n");
      issue15++;
    }
  }
  UNLOCK_WIFI();
  return ret;
}

 

LOCK_WIFI() пустышка.

до USART_SendInt я не дохожу так как условие if (WIFI_STATUS_OK == WIFI_ReceiveData(SOCKET, udp_rx_buf, 1000, &udp_rx_len, 1000 )) не выполняется.

 

Тогда я лично в потемках. Явно кто-то грузит процессор так, что прерывание не успевает выбрать регистр данных, и возникает переполнение. Это может быть связано с длинной пост-обработкой принятого прерыдущего байта в самом прерывании. Попробуйте "зациклиться" в прерывании по приему, пока не упадет флаr RXNE: то есть, не "сработало прерывание по RXNE - байт выбран, обработали, вышли", а "сработало прерывание по RXNE - выбираем байты в цикле с проверкой RXNE, пока он не упадет, потом вышли".

 

Еще идеи:

1. Наверное AT_ExecuteCommand() посылает что-то через UART/SPI? Это то, о чем я говорил в части интенсивной передачи и DMA.

2. Может ваш приемный буфер, куда складываются принятые байты, по глубине равен 1? Типа недоглядели какой #define...

Изменено пользователем KnightIgor

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

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