Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: freertos+ppp
Форум разработчиков электроники ELECTRONIX.ru > Cистемный уровень проектирования > Операционные системы > FreeRTOS
cpl
Здравствуйте прошу помощи, не могу разобраться что не так...

платформа avr32+gnu+eclipse.
От железа требуется подключиться к удаленному серверу по gprs и передать накопленные данные.
Решил отрабатывать программу по частям, написал скелет программы, rtos запустил, ppp поднял,
отрабатываю запуск ppp-gprs соединения и закрытие gprs соединения, начинает вываливаться в исключение.

есть две задачи одна отвечает за поднятие ppp соединения и передачу данных по gprs(vTaskPPPStart), вторая за запуск vTaskPPPStart когда это требуется (vTaskWaitSMS)

задачи обмениваются сообщениями через очереди.
поднятие соединения происходит нормально, при закрытии gprs задача vTaskPPPStart ждет сообщения об успешном закрытием соединения (получает его) и посылает сообщение задаче vTaskWaitSMS
и тут вываливается в исключение, исключение происходит внутри rtos в функции xQueueGenericSend
на taskEXIT_CRITICAL();
pxQueue=0xfdfdfdfd pvItemToQueue=0xfdfdfdfd явно указывают не на ram.

freertos настроена на работу в приоритетном планировании, работа с памятью heap_3.
размер стека 4кб, размер стека задачи 256, приоритеты задач (tskIDLE_PRIORITY + 2)
пробовал увеличивал размер стека до 8к, у задач до 1024 все равно вываливается в исключение.
вызывал в каждой задаче uxTaskGetStackHighWaterMark получалось значения от 200 т.е. так понимаю запас у задач хороший.

посмотрел размер используемой памяти avr32-size.exe bin.elf

text data bss dec hex filename
135436 1772 31088 168296 29168 bin.elf
получается что около половины рам остается под кучу.

обновил rtos с версии 4 до версии 6.
Обновил gсс.
Куда копать дальше ?
smile3046.gif

исходник задач:
Код
static void vTaskWaitSMS( void *pvParameters ){

    sms_state_t sms_state;
    portSHORT message_ppp;
    xTaskHandle xTH_pppstart;

    led_blink_out = RG_ON;
    sms_state = STATE_WAIT_SMS;

    xTaskCreate( vTaskPPPStart, (const signed portCHAR *)"PPPStart", configMINIMAL_STACK_SIZE, NULL, mainPPPSTART_TASK_PRIORITY, &xTH_pppstart );

    for(;;){
        switch (sms_state){
        case STATE_WAIT_SMS:

            vTaskDelay(1000);
            // запускаем задачу vTaskPPPStart
            printf("start vTaskPPPStart\n");
            vTaskResume(xTH_pppstart);
            sms_state = STATE_RUN_GPRS;
            break;
        case STATE_RUN_GPRS:
                if (xQueueReceive(xMsgPPPstart, &message_ppp, (portTickType)500) == pdTRUE){
                    printf("read message from PPP=%x\n",message_ppp);
                    printf("delay 3 sec.\n");
                    //vTaskDelay(3000);
                    printf("delay ok.\n");
                    sms_state = STATE_WAIT_SMS;

                }
                else
                {
                    printf("*");
                    vTaskDelay(1000);
                }


            break;
        }

    }

}

static void vTaskPPPStart( void *pvParameters )
{
    portBASE_TYPE   pdResult;
    char    arucRcvBuffer[32];
    sio_fd_t sioModem = EXAMPLE_USART1;

    pppstart_state_t pppstart_st;
    pppstart_st = STATE_IDLE;
    pppstatuscv_t msg_in;    // входное сообщение от pppstartcb
    int        ppp_con_fd;
    int err;
    err_t error;
    sys_sem_t sem;
    portSHORT err_tcp;
    struct netbuf *buf;
    struct netconn *conn;
    struct ip_addr addr;
    u16_t data_len;
    int i;


    lwip_init();

    sem = sys_sem_new(0); // Create a new semaphore.
    tcpip_init(tcpip_init_done, &sem);
    sys_sem_wait(sem); // Block until the lwIP stack is initialized.
    sys_sem_free(sem); // Free the semaphore.

    pppInit();


    for(;; )
    {
        switch(pppstart_st){
        case STATE_IDLE:
            printf("STATE_IDLE\n");
            //task_list();
            printf("vTaskPPPStart suspend.....\n");
            vTaskSuspend(NULL);
            pppstart_st = STATE_DIAL;
            break;
        case STATE_DIAL:
            printf("STATE_DIAL\n");
            led_blink_out = G_BLINK;


            pppstart_st = STATE_OPEN_PPP;
            break;

        case STATE_OPEN_PPP:
            printf("STATE_OPEN_PPP\n");
            ppp_con_fd = pppOverSerialOpen( sioModem, vPPPStatusCB, NULL );
            APPIP_TRACE( ( "vAppIP(STATE_PPP_INIT): opening ppp connection\r\n") );
            printf("ppp_con_fd=%x\n",ppp_con_fd);

            pppstart_st = STATE_CONNECTION_PPP;
            break;

        case STATE_CONNECTION_PPP:
            printf("STATE_CONNECTION_PPP\n");
            if ( xMsgPPPstatusCB != 0 ){// очередь существует
                pdResult = xQueueReceive(xMsgPPPstatusCB, &msg_in, (portTickType)500);
                if( pdResult == pdTRUE ){
                    led_blink_out = G_ON;
                    printf("read message from PPPstartcb=%x\n",msg_in);
                    //pppstart_st = STATE_DATA_TRANSFER;
                    pppstart_st = STATE_CLOSE_PPP;
                }
            }
            break;

        case STATE_CLOSE_PPP:
            printf("STATE_CLOSE_PPP\n");
            led_blink_out = RG_BLINK;
            //task_list();
            err = pppClose( ppp_con_fd );
            printf("\npppClose result=%d\n",err);
            //task_list();
            //vTaskDelay(1000);// если ракломентирывать то здесь будет исключение
            pppstart_st = STATE_WAIT_CLOSE_PPP;
            break;

        case STATE_WAIT_CLOSE_PPP:
            printf("STATE_WAIT_CLOSE_PPP\n");
            if ( xMsgPPPstatusCB != 0 ){// очередь существует
                pdResult = xQueueReceive(xMsgPPPstatusCB, &msg_in, (portTickType)500);
                printf("#");
                if( pdResult == pdPASS ){
                    printf("STATE_WAIT_CLOSE_PPP read message from PPPstartcb=%x\n",msg_in);
                    if (msg_in == CLOSE_MSG){
                        printf("STATE_WAIT_CLOSE_PPP read message from PPPstartcb=CLOSE_MSG\n");
                        pppstart_st = STATE_IDLE;
                        led_blink_out = RG_ON;
                        err_tcp = PPPERR_HIGH | (error & 0xff);
                        while(xQueueSend(xMsgPPPstart, &err_tcp, 100) != pdPASS);
                        printf("STATE_WAIT_CLOSE_PPP send mesg ok\n");

                    }
                    pppstart_st = STATE_IDLE;
                }
                if (pdResult == errQUEUE_EMPTY)
                    printf("errQUEUE_EMPTY");
            }
            break;
        }
    }
}

extern xSemaphoreHandle xUartConsolOSsem;

ATTRIBUTE_CLIB_SECTION
int
printf(const char *fmt, ...)
{
    va_list ap;
    int i;

    while(xSemaphoreTake(xUartConsolOSsem, (portTickType)10) == pdTRUE);

    va_start(ap, fmt);
    i = vfprintf(stdout, fmt, ap);
    va_end(ap);

    xSemaphoreGive(xUartConsolOSsem);

    return i;
}
static void vTaskLedBlink( void *pvParameters )
{
    for(;; )
    {
        switch(led_blink_out){
        case R_ON:
            LED_STATUS_R_ON;
            LED_STATUS_G_OFF;
            vTaskDelay(500);
            break;
        case G_ON:
            LED_STATUS_G_ON;
            LED_STATUS_R_OFF;
            vTaskDelay(500);
            break;
        case RG_ON:
            LED_STATUS_R_ON;
            LED_STATUS_G_ON;
            vTaskDelay(500);
            break;
        case G_BLINK:
            LED_STATUS_R_OFF;
            LED_STATUS_G_ON;
            vTaskDelay(500);
            LED_STATUS_G_OFF;
            vTaskDelay(500);
            break;
        case R_BLINK:
            LED_STATUS_G_OFF;
            LED_STATUS_R_ON;
            vTaskDelay(500);
            LED_STATUS_R_OFF;
            vTaskDelay(500);
            break;
        case RG_BLINK:
            LED_STATUS_R_ON;
            LED_STATUS_G_ON;
            vTaskDelay(500);
            LED_STATUS_R_OFF;
            LED_STATUS_G_OFF;
            vTaskDelay(500);
            break;
        default:
            break;
        }
    }
}


лог работы:
Код
TCP_INIT DONE.
STATE_IDLE
vTaskPPPStart suspend.....
start vTaskPPPStart
STATE_DIAL
.......
STATE_OPEN_PPP
vAppIP(STATE_PPP_INIT): opening ppp connection
ppp_con_fd=0
STATE_CONNECTION_PPP
STATE_CONNECTION_PPP
STATE_CONNECTION_PPP
*STATE_CONNECTION_PPP
STATE_CONNECTION_PPP
STATE_CONNECTION_PPP
*STATE_CONNECTION_PPP
STATE_CONNECTION_PPP
STATE_CONNECTION_PPP
*STATE_CONNECTION_PPP
STATE_CONNECTION_PPP
STATE_CONNECTION_PPP
*STATE_CONNECTION_PPP
STATE_CONNECTION_PPP
STATE_CONNECTION_PPP
*STATE_CONNECTION_PPP
STATE_CONNECTION_PPP
STATE_CONNECTION_PPP
*STATE_CONNECTION_PPP
vPPPStatusCB: error code = none
vPPPStatusCB: PPP link reported connection established.
read message from PPPstartcb=0
STATE_CLOSE_PPP
vPPPStatusCB: error code = connect
vPPPStatusCB: PPPERR_CONNECT!
pppClose result=0
vPPPStatusCB: error code = user
vPPPStatusCB: PPPERR_USER!


eisufu
Интересно было бы узнать о развитии событий...
cpl
Все оказалось достаточно тривиально,
как выяснилось одна из задач стека lwip pppmain если память не изменяет,
приводила к исключению, причина проста: по завершению работы задача завершалась просто выходя из вечного цикла !
Сложилось впечатление, что мне одному это неизвестно было.....

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

Есть еще вопросы, разбираюсь по возможности в перерывах между боями.

Сравнивал с поднятием подобной задачи на линуксе время затратил недели две от силы, в общем даже по проще будет,
т.к. меньше возни на ровном месте.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2024 Invision Power Services, Inc.