реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> STM32+LWIP+PPP проблемы с аутентификацией
Klapatun
сообщение Jul 13 2018, 09:53
Сообщение #1





Группа: Участник
Сообщений: 5
Регистрация: 12-07-18
Из: Новосибирск
Пользователь №: 105 858



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

Имеется 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 ( 15.92 килобайт ) Кол-во скачиваний: 8
Прикрепленный файл  ppp_connect.pdf ( 200.95 килобайт ) Кол-во скачиваний: 7
 
Go to the top of the page
 
+Quote Post
CADiLO
сообщение Jul 13 2018, 10:16
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 6 023
Регистрация: 26-08-05
Из: Днепр
Пользователь №: 7 988



В свое время для 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% клиентов пользуются встроенными возможностями.
А кому хочется поэкспериментировать, то.....


--------------------
Не можна втрачати надію. Не можна здаватися до останньої миті. Можливо саме вона, остання мить, принесе весну, яка стане початком нового життя.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jul 13 2018, 11:47
Сообщение #3


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (Klapatun @ Jul 13 2018, 12:53) *
и при фиксации второго HDLC-заголовка (0x7E), отправляет данные в lwip функцией `pppos_input`.
Это некорректно. Дело в том, что первый заголовок передается только если была большая пауза после предыдущего пакета. А на стадии установки соединения паузы маленькие и часть пакетов идет без первого заголовка. Посмотрите мое сообщение в соседней ветке, там я приводил лог установки соединения.
В виденных мной реализациях (и в моей тоже) пакет передается в стек при наступлении паузы в 1-2 мс. Но ваша идея мне в целом нравится - если приняли 0x7E и в буфере больше одного байта - можно смело передавать пакет. Пожалуй, сделаю и у себя так.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
alex2103
сообщение Jul 13 2018, 12:42
Сообщение #4


Частый гость
**

Группа: Свой
Сообщений: 135
Регистрация: 7-03-07
Из: г. Запорожье
Пользователь №: 25 945



У меня тоже сделано по второму 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;
}
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jul 13 2018, 13:03
Сообщение #5


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (alex2103 @ Jul 13 2018, 15:42) *
У меня тоже сделано по второму 0x7E. Не замечал пакетов без заголовка.
Видишь суслика? А он есть!
Выше привел лог, в котром такие пакеты есть. Впрочем, я не настаиваю.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Klapatun
сообщение Jul 18 2018, 08:28
Сообщение #6





Группа: Участник
Сообщений: 5
Регистрация: 12-07-18
Из: Новосибирск
Пользователь №: 105 858



Цитата(alex2103 @ Jul 13 2018, 19:42) *
Может 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, но там не было ответов на этот вопрос ответа не было.
Go to the top of the page
 
+Quote Post
Grigorij
сообщение Jul 19 2018, 08:11
Сообщение #7


Участник
*

Группа: Участник
Сообщений: 71
Регистрация: 10-03-07
Пользователь №: 26 038



День добрый

У меня сейчас в приборе как раз работает связка 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
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 16th April 2024 - 07:43
Рейтинг@Mail.ru


Страница сгенерированна за 0.01454 секунд с 7
ELECTRONIX ©2004-2016