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

STM32+LWIP+PPP проблемы с аутентификацией

Доброго времени суток!

 

Имеется sim-карта со статическим IP и модем SIM800C, который через UART соединен с STM32F0. Пытаюсь обойтись без встроенного в модем стека, чтобы обеспечить себе беззаботную жизнь, когда придет нужда менять модем, для этого в качестве внешнего стека юзаю lwip.

 

Видел на хабре статью про это дело, которая, собственно, и являлась отправной точкой, было решено повторить подвиг, но в версии lwip 2.0.3, которой я пользуюсь, ppp немного изменился и это все хорошо описано в документации (ppp.txt, прикреплю его ниже). Следуя инструкциям из упомянутого файла, реализовал все функции, которые надо реализовать и все заработало.... почти. Когда модем начал общаться с контроллером, дальше фазы LCP дело не зашло. Как я понял из документа (ppp_connect.pdf), который оказался у меня уже-и-не-помню-откуда, после конфигурирования параметров соединения в фазе LCP контроллер должен посылать в модем пакет с заголовком PAP (C0 23), но он почему-то этого не делает... Он вообще больше ничего не делает. Я пытался проследить в отладчике весь путь запроса, что приходит от модема, но это только больше меня запутало.

 

Собственно, прием данных у меня организован через прерывание. После ввода AT-команды "ATD*99***1#" и получения ответа "CONNECT", устанавливается флаг "ppp_enable" и при приходе байта он кладется в очередь `xQueue_PPP_Package`.

 

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  uint8_t u8;
  if(huart == &huart1)
  {

    if (ppp_enable == true)
    {
      portBASE_TYPE xHigherPriorityTaskWoken_PPP_Rx;

      u8 = Sim800.UsartRxTemp;

      xHigherPriorityTaskWoken_PPP_Rx = pdFALSE;
      xQueueSendFromISR(xQueue_PPP_Package, &u8, &xHigherPriorityTaskWoken_PPP_Rx);
    }
    else
    {
      /*Reception of AT commands*/
    }

    HAL_UART_Receive_IT(&huart1,&Sim800.UsartRxTemp,1);
  }
}

 

В задаче `StartLwIPTask` в бесконечном цикле проверяется эта очередь и при появлении элементов, записывает их в массив `PPPx.Data` и при фиксации второго HDLC-заголовка (0x7E), отправляет данные в lwip функцией `pppos_input`.

 

P.S. Переменная `PPPx.Last_Index` это размер пришедшего ppp-пакета.

 

void StartLwIPTask(void const * argument)
{
  /* USER CODE BEGIN StartLwIPTask */
  /*Создаем очередь*/
  xQueue_Sim800_Package = xQueueCreate(128, sizeof(uint8_t));
  xQueue_PPP_Package = xQueueCreate(128, sizeof(uint8_t));
  uint8_t u8=0;
  volatile int setup = 0;

  tcpip_init( NULL, NULL );             /*Инициализация стека tcp/ip*/

  /*Create a new PPPoS interface*/
    ppp = pppos_create(&ppp_netif,
         output_cb, status_cb, 0);

//    
    /* Auth configuration, this is pretty self-explanatory */
    ppp_set_auth(ppp, PPPAUTHTYPE_PAP, "beeline", "beeline");


    /* Require peer to authenticate */
    ppp_set_auth_required(ppp, 1);

    /*Only for PPPoS, the PPP session should be up and waiting for input.*/
    ppp_set_silent(ppp, 1);

    /*
    * Initiate PPP listener (i.e. wait for an incoming connection), can only
    * be called if PPP session is in the dead state (i.e. disconnected).
    */
    ppp_listen(ppp);

  /* Infinite loop */
  for(;;)
  {    
    if (sim800_init() == S_RESET)          /*Настройка модуля Sim800*/
      continue;


    for (;;)
    {

      if (pdPASS == xQueueReceive(xQueue_PPP_Package, &u8, 100/portTICK_RATE_MS))
      {
        if (u8 == 0x7E)
          t++;

        PPPx.Data[PPPx.Last_Index++] = u8;

        if (t==2)
        {
          PPPx.Last_Index--;
          pppos_input(ppp, PPPx.Data, PPPx.Last_Index);
          t=0;
          memset(&PPPx, 0, sizeof(PPPx));
        }
      }      
    }
  }
  /* USER CODE END StartLwIPTask */
}

 

Как я писал выше, все идет хорошо, пока идет фаза LCP, но после подтверждения контроллером запроса опций, наступает тишина. Интуиция мне говорит, что у меня какой-то косяк в настройках ppp в lwip, но неопытность в этом вопросе мешает понять, где именно и что именно я делаю не так

 

В интернете мне удалось найти довольно мало исчерпывающей информации и примеров по связке stm32+lwip+ppp (не исключаю, что это просто я искать не умею, если поделитесь ссылками на полезные ресурсы, буду очень признателен), если кто-нибудь занимался подобным или сталкивался с похожей проблемой, буду ноги целовать очень благодарен за помощь и за пинки в нужном направлении.

ppp.txt

ppp_connect.pdf

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


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

В свое время для SIM900 рекомендовалось следующее:

 

The reason PPP information is not given for SIM900 is SIM900 need to initiate the negotiate process firstly after the “CONNECT” is shown. In fact, after you have seen the string of “CONNECT”, if you input

“7E FF 7D 23 C0 21 7D 21 7D 20 7D 20 7D 37 7D 22 7D 26 7D 20 7D 20 7D 20 7D 20 7D 25 7D 26 3C 3D 48 83 7D 27 7D 22 7D 28 7D 22 7D 2D 7D 23 7D 26 30 51 7E”

in the serial port, you will see the negotiate process for PPP in SIM900.

 

 

Для 800 серии не знаю, так как наши 99% клиентов пользуются встроенными возможностями.

А кому хочется поэкспериментировать, то.....

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


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

и при фиксации второго HDLC-заголовка (0x7E), отправляет данные в lwip функцией `pppos_input`.
Это некорректно. Дело в том, что первый заголовок передается только если была большая пауза после предыдущего пакета. А на стадии установки соединения паузы маленькие и часть пакетов идет без первого заголовка. Посмотрите мое сообщение в соседней ветке, там я приводил лог установки соединения.

В виденных мной реализациях (и в моей тоже) пакет передается в стек при наступлении паузы в 1-2 мс. Но ваша идея мне в целом нравится - если приняли 0x7E и в буфере больше одного байта - можно смело передавать пакет. Пожалуй, сделаю и у себя так.

 

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


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

У меня тоже сделано по второму 0x7E. Не замечал пакетов без заголовка.

 

Может ppp_set_auth_required(ppp, 1); ppp_set_silent(ppp, 1); ppp_listen(ppp); лишние?

 

ppp = pppos_create(&ppp_netif, output_cb, status_cb, NULL);
ppp_set_auth(ppp, PPPAUTHTYPE_PAP,user,pass);
pppapi_set_default(ppp);
ppp_connect(ppp, 1);
while ((!PPPconnected) && (--timeout>0) && (PPPerror == PPPERR_NONE))
            {
                osDelay(1000);
            }

            if (timeout>0 && (PPPerror == PPPERR_NONE))
            {
//conected;
                         }

 

В status_cb:

 

case PPPERR_NONE:

{

PPPconnected = 1;

}

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


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

У меня тоже сделано по второму 0x7E. Не замечал пакетов без заголовка.
Видишь суслика? А он есть!

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

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


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

Может ppp_set_auth_required(ppp, 1); ppp_set_silent(ppp, 1); ppp_listen(ppp); лишние?

 

ppp = pppos_create(&ppp_netif, output_cb, status_cb, NULL);
ppp_set_auth(ppp, PPPAUTHTYPE_PAP,user,pass);
pppapi_set_default(ppp);
ppp_connect(ppp, 1);
while ((!PPPconnected) && (--timeout>0) && (PPPerror == PPPERR_NONE))
            {
                osDelay(1000);
            }

            if (timeout>0 && (PPPerror == PPPERR_NONE))
            {
//conected;
                         }

 

Попробовал ваш вариант, но у меня на функции "pppapi_set_default(ppp);" в "tcpip_api_call" застревает программа при разблокировки ядра TCPIP в "UNLOCK_TCPIP_CORE();".

Согласно документации достаточно только включить #include "pppapi.h" и поставить LWIP_PPP_API 1, что я и сделал, но появившаяся проблема вводит меня в ступор и понять ее причину я не могу. Может, я как-то совсем не так настраиваю lwip и причину надо искать где-нибудь в заголовочных файлах?

 

Так же заметил, что status_cb в принципе не вызывается. Нашел подобную проблему на stack overflow, но там не было ответов на этот вопрос ответа не было.

 

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


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

День добрый

 

У меня сейчас в приборе как раз работает связка SIM800C+STM32F405+LWIP+FreeRTOS. Версия LWIP 2.0.0, но в ней вроде как нет глобальных отличий от 2.0.3 в плате PPPOS.

 

По сравнению с вашим кодом:

 

1) Для передачи данных в LWIP я использую ф-цию pppos_input_tcpip()

2) После того, как я получил сообщение CONNECT от модем, я перестаю сам анализировать данные, и все данные от модема полностью передаю в LWIP на обработку

 

 

Порядок включения и работы с LWIP и PPP у меня примерно следующий:

 

    sys_sem_new(&sem, 0);
        tcpip_init(TCPIPDoneCB, &sem);
        sys_sem_wait(sem);
    sys_sem_free(sem);

    pppapi_pppos_create(...,PPPOSOutputCB, PPPOSStatusCB, ...)

    ppp_set_usepeerdns(ctx->network.ppp, 1);    // только если DNS нужен

    ppp_set_auth(...., PPPAUTHTYPE_CHAP, user, password);

    pppapi_set_default();

    pppapi_connect();


static u32_t PPPOSOutputCB(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx)
{
    LWIP_UNUSED_ARG(pcb);
    LWIP_UNUSED_ARG(ctx);

    // шлем данные в UART как есть, без какого-либо разбора

    return sio_write(0, data, len);
}

static void PPPOSStatusCB(ppp_pcb *pcb, int err_code, void *ctx)
{
    ...

    switch (err_code)
    {
        case PPPERR_NONE:
        {
            // здесь уже есть IP у прибора
        }
        // обработка других кодов
    }
}

// есть отдельная задача, в которой вызывается следующая функция, которая 
// в свою очередь забирает данные с UART и прямиком без какого-либо разбора отправляет 
// их в LWIP. 

void GSMrocessData(struct ModemContext *ctx)
{
    // gsmRawRxBuf - буфер для данных
    // GSM_RAW_RX_BUF_SIZE - максимальный размер буфера (должен быть около 1600 байт, у меня 2048)
    // 10 - таймут на ожидания данных в мс.
    // rb - количество данных полученных от модема 

    int rb = sio_read(gsmRawRxBuf, GSM_RAW_RX_BUF_SIZE, 10);
    if (rb)
    {
        pppos_input_tcpip(ppp, (u8_t *)gsmRawRxBuf, rb);
    }
}

 

Также не стоит забывать о настроке самой LWIP (часть для PPP)

 

// PPP

#define PPP_SUPPORT                 1
#define PPPOS_SUPPORT               1
#define PPP_IPV4_SUPPORT            1
#define PAP_SUPPORT                 1
#define CHAP_SUPPORT                1

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


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

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

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

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

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

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

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

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

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

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