STM32F4: Почему моя программа зависает, когда я использую USART (GPS) и uSD (FatFs) одновременно? - PullRequest
1 голос
/ 10 марта 2020

Короткая история

Я работаю над проектом на основе STM32F469, в котором я хотел бы, среди прочего, сохранить данные GPS (из Adafruit Ultimate GPS Breakout V3) на карту USB (управляемую через SPI). интерфейс со слоем FatFs). Я использую по существу библиотеку HAL для инициализации и управления периферийными устройствами. Программа использует много периферийных устройств и до сих пор все работало нормально (RT C, I2 C, UART, SPI, LTCD, DSI, RAM и др. c ...).

Я борюсь с картой USB для сохранения данных GPS: моя программа зависает, когда я решаю остановить обработку данных GPS и закрыть файл.

Прежде чем мы go продолжим:

  • Я уже использовал в этом же проекте SD-карту для сохранения и извлечения различных данных из и в файл .csv (другая часть программы): он был и все еще прекрасно работает, когда Я делаю это. Как я уже говорил, управление uSD осуществляется через интерфейс SPI и FatFs;
  • Связь GPS осуществляется через периферийное устройство USART6 с управлением прерываниями (IRQ на каждый полученный байт). Если я не использую часть USB с GPS, я получаю данные GPS, могу отобразить их на экране и остановить прием. Если я использую часть USB с GPS, я получаю данные GPS, могу отображать их на моем экране, пока я не прекращаю прием. Когда я прекращаю прием (и затем решаю закрыть файл), программа останавливается (или что-то ждет).

Функции

// The program goes into this part of the program when I push a button

// GPS enabled

// HMI display
DGT_DisplayStringLCD(RECO_GPS_VALX, RECO_GPS_VALY, (uint8_t *)"ENABLED", CENTER);

// USART6 initialization with IRQ
GPIO_InitTypeDef  GPIO_InitStruct;

__HAL_RCC_GPIOG_CLK_ENABLE();
__HAL_RCC_USART6_CLK_ENABLE();

GPIO_InitStruct.Pin       = USART_TX_PIN;
GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull      = GPIO_PULLUP;
GPIO_InitStruct.Speed     = GPIO_SPEED_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF8_USART6;

HAL_GPIO_Init(USART_TX_BASE, &GPIO_InitStruct);

GPIO_InitStruct.Pin         = USART_RX_PIN;
GPIO_InitStruct.Alternate   = GPIO_AF8_USART6;

HAL_GPIO_Init(USART_RX_BASE, &GPIO_InitStruct);

huart->Instance             = USART6;

huart->Init.BaudRate        = 9600;
huart->Init.WordLength      = UART_WORDLENGTH_8B;
huart->Init.StopBits        = UART_STOPBITS_1;
huart->Init.Parity          = UART_PARITY_NONE;
huart->Init.Mode            = UART_MODE_TX_RX;
huart->Init.HwFlowCtl       = UART_HWCONTROL_NONE;

if(HAL_UART_Init(&uart6Handle) != HAL_OK){
    return HAL_ERROR;
}

__HAL_UART_ENABLE_IT(huart, UART_IT_ERR);
__HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);

HAL_NVIC_SetPriority(USART6_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(USART6_IRQn);


// IRQ when 1 byte is received
HAL_UART_Receive_IT(&uart6Handle, (uint8_t*)USART6_RXBuffer, 1);

// GPS configuration
GPS_Config();

// uSD configuration
if(FATFS_LinkDriver(&SD_Driver, SDPath) == 0){
    if(BSP_SD_Init() != MSD_OK){
        FATFS_UnLinkDriver(SDPath);
        err = HAL_ERROR;
    }else{
        if(f_mount(&SDFatFs, (TCHAR const*)SDPath, 0) != FR_OK){
            FATFS_UnLinkDriver(SDPath);
            err = HAL_ERROR;
        }else{
            sprintf(csvPath, "gpsrec%u.txt", 1);
            err = f_open(&MyCSVFile, (TCHAR const*)csvPath, FA_WRITE | FA_READ | FA_CREATE_ALWAYS);
            GPS_RecordInit(&MyCSVFile); // Write header
        }
    }
}else{ // FatFs_LinkDriver error
    FATFS_UnLinkDriver(SDPath);
    err = HAL_ERROR;
}

В этой части программы Когда я решаю «включить» GPS, я инициализирую периферийное устройство USART6 и его прерывания (ERR & RXNE). Когда это будет сделано, я вызываю функцию HAL_UART_Receive_IT для 1 байта. Таким образом, прерывание возникает у каждого символа, полученного от GPS, который обрабатывается в функцию обратного вызова (см. Ниже). Функция GPS_Config () используется для настройки карты GPS (только RM C, скорость передачи данных). Наконец, я настраиваю карту USB с функцией FatFs. Это делается так же, как я делаю это в другой части программы, где она работает нормально. Когда я настраиваю карту USB, я открываю файл и записываю в него заголовок.

// GPS is disabled

// HMI Display
DGT_DisplayStringLCD(RECO_GPS_VALX, RECO_GPS_VALY, (uint8_t *)"DISABLED", CENTER);

// IRQ disabled
HAL_NVIC_DisableIRQ(USART6_IRQn);

// Clear the buffer (useless ?)
HAL_UART_Receive(&uart6Handle, dummyBuffer, 9, 100);

// Reset USART6 peripheral
HAL_UART_DeInit(&uart6Handle);
__HAL_UART_DISABLE_IT(&uart6Handle, UART_IT_ERR);
__HAL_UART_DISABLE_IT(&uart6Handle, UART_IT_RXNE);
uart6Handle.RxState = HAL_UART_STATE_READY;

// Write the footer
GPS_RecordEnd(&MyCSVFile);

// Close the file
f_close(&MyCSVFile);

// Unlink the driver
FATFS_UnLinkDriver(SDPath);

Эта часть программы - то, что делается, когда я решаю «отключить» GPS. Я отключаю прерывание USART6. Следующая функция HAL_UART_Receive используется для очистки буфера. Я перезагружаю периферию USART6. Наконец, я записываю нижний колонтитул в свой файл, закрываю файл и отсоединяю драйвер. Эта часть программы претерпела множество изменений, так как именно здесь моя программа зависает. Я безуспешно переключил функции вызова заказов в США / GPS. Это больше не является надежным, но я просто пытаюсь на данный момент закрыть свой файл и прочитать то, что я написал.

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){

    if(huart->Instance == USART6){

        if(RMCProcessing == 0){
            // Only process char received if a RMC 
            // frame is not already in process

            if(USART6_RXBuffer[0] == '$'){
                // char received id the beginning of the RMC frame

                RMCReception = 1;   // Frame receiving
                RMCProcessing = 0;  // Prevent the GPSProcess function to process the current frame until it is received

                // Save the first char received
                RX_GPSBuffer[inc] = USART6_RXBuffer[0];
                inc++;

            }else{
                // The char received is in the middle of the frame

                if(RMCReception){
                    // It is part of the current detected RMC frame (middle or end ?)

                    if(USART6_RXBuffer[0] == '\n'){
                        // End of the frame detected

                        RX_GPSBuffer[inc] = USART6_RXBuffer[0];
                        inc = 0;    // Reset the buffer
                        RMCReception = 0; // Frame completely received
                        RMCProcessing = 1; // The frame can be process by GPSProcess()

                    }else{
                        // Middle

                        RX_GPSBuffer[inc] = USART6_RXBuffer[0];
                        inc++;

                        if(inc >= 250){
                            // To prevent unexpected error

                            inc = 0; 
                            RMCReception = 0; 
                            RMCProcessing = 0;

                        }

                    }

                }else{
                    // Char is ignored
                    // Reset the buffer and process state

                    inc = 0; // Reset the buffer
                    RMCReception = 0;
                    RMCProcessing = 0;

                }


        }


        HAL_UART_Receive_IT(&uart6Handle, (uint8_t*)USART6_RXBuffer, 1);


}

Это функция обратного вызова для периферийного устройства USART6 (когда я получаю байт ). Ничего особенного, я думаю. Он служит только для обнаружения и сохранения в буфер кадра RM C с GPS. Полученный кадр RM C затем обрабатывается в функции, помещенной в некоторое время l oop (здесь не актуально, но я могу добавить его, если будет предложено).

Просто напоминание:

  • В эти функции я даже не записываю данные GPS на карту USB (я пишу только верхний и нижний колонтитулы). Часть, где я сохраняю данные GPS на карту uSD, закодирована, но пока прокомментирована. Поскольку у меня есть проблема без какой-либо экономии, я не думаю, что она актуальна;
  • Если я только прокомментирую часть USB, записанную в этих функциях, я могу включить, получить и отобразить все данные GPS. Я могу отключить GPS. Нет проблем, моя программа все еще работает нормально;
  • Если я только комментирую часть USART6, я могу смонтировать, открыть, записать и закрыть файл столько раз, сколько захочу. Когда я отключаю карту USB и читаю ее содержимое на P C, у меня есть файл и его содержимое (верхний и нижний колонтитулы);
  • Если я использую функции в том виде, как они здесь отображаются (еще не очищены), я могу получать данные GPS, без ошибок (очевидно), когда я монтирую и записываю в свой файл, но когда я останавливаю GPS (и решаю закрыть свой файл ). Программа зависает (или зависает, я не знаю).

Подсказка

Я подозреваю, что проблема с управлением IRQ USART6, но я не знаю, каким образом , Позвольте мне объяснить: пару раз GPS плохо инициализировался (или GPS не получал никаких данных от спутников?). Данные GPS не отображались, даже если я их включил. В этот момент я смог отключить его без остановки. Я думаю, что замораживание происходит, когда буфер RX не пуст (или когда IRQ не повышен, я действительно не знаю).

В любом случае, у вас есть какие-либо идеи, почему у меня такое поведение?

Спасибо!

...