Короткая история
Я работаю над проектом на основе 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 не повышен, я действительно не знаю).
В любом случае, у вас есть какие-либо идеи, почему у меня такое поведение?
Спасибо!