id_soft 0 15 апреля, 2011 Опубликовано 15 апреля, 2011 · Жалоба Пишу под FREErtos для sam3s (Cortex-M3). В одной из задач, которая общается через UART возможно происходит утечка стека(возможно потому, что я не могу это пока подтвердить). Программа работает некоторое время, затем начинает сбоить передача в UART, при этом остальные задачи работают нормально. Увеличение размера стека приводит к увеличению времени нормальной работы. С помощью внутрисхемной отладки выяснил, что сбои передачи заключается в опережении указателя чтения(pxReadFrom) указателя записи(pcWriteTo) очереди на передачу в UART. Есть подозрение на прерывание UART. Я не использую никаких атрибутов для функции-обработчика прерывания(в примере их не было), хотя когда писал для sam7 использовал naked. Функция vTaskList показывает, что использование стека стоит на месте. Пытаюсь вставить в код процесса критическую секцию - все зависает. Код процесса: void vShellThread(HANDLE xPort) { SHELL xShell = { xPort, xShellCommands }; char pcInputLine[sHELL_MAX_INPUT_LEN]; char *pcToken, *pcNextToken; char *pcArgs[sHELL_MAX_ARGUMENTS + 1]; char *pcCmd; uint32_t uiArgsCount = 0; if (!xSerialIsOpen(xShell.xSerialPort)) assert(!"Serial port for shell not opened."); // print shell header xSerialPutString(xShell.xSerialPort, "Shell command interface v0.1.\n", 1000); // set local echo enabled xSerialSetEchoEnabled(xPort, pdTRUE); while (pdTRUE) { xSerialPutString(xShell.xSerialPort, "shell$ ", 1000); if (xSerialGetLine(xShell.xSerialPort, pcInputLine, SHELL_MAX_INPUT_LEN, 6000) != pdPASS) { xSerialPutString(xShell.xSerialPort, "\nERR: too long input line.\n", 1000); //continue; } // get command pcToken = strtok_m(pcInputLine, pcShellSeparators, &pcNextToken); if (pcToken == NULL) continue; pcCmd = pcToken; uiArgsCount = 0; // get arguments while (pcNextToken != NULL) { pcToken = strtok_m(NULL, pcShellSeparators, &pcNextToken); if (uiArgsCount > SHELL_MAX_ARGUMENTS) { xSerialPutString(xShell.xSerialPort, "\nERR: max arguments limit\n", 1000); pcCmd = NULL; break; } pcArgs[uiArgsCount++] = pcToken; } pcArgs[uiArgsCount] = NULL; if (pcCmd != NULL) { if (!prvShellExec(&xShell, pcCmd, uiArgsCount, pcArgs)) xSerialPutString(xPort, "Unknown cmd. Type help for information.\n", 100); } xSerialPutString(xPort, "Unknown cmd. Type help for information.\n", 1000); } } Код используемых функций: signed portBASE_TYPE xSerialPutString(HANDLE xPort, char *pcString, portTickType xBlockTime) { while (*pcString != '\0') { if (xSerialPutChar(xPort, *pcString++, xBlockTime) != pdPASS) return pdFAIL; } return pdPASS; } signed portBASE_TYPE xSerialPutChar(HANDLE xPort, const char cOutChar, portTickType xBlockTime) { USART_PORT *port = (USART_PORT*) xPort; assert (xPort != NULL); if (xQueueSend(port->xTransmitQueue, &cOutChar, xBlockTime) != pdPASS) return pdFAIL; USART_EnableIt(port->xHwPort, US_IER_TXRDY); return pdPASS; } signed portBASE_TYPE xSerialGetLine(HANDLE xPort, char *pcDest, uint32_t iMaxLen, portTickType xBlockTime) { char c; uint32_t len = 0; while (xSerialGetChar(xPort, &c, xBlockTime) == pdPASS) { if ((c != '\n') && (c != '\r') && (c != '\b')) { if (++len == iMaxLen) return pdFAIL; *pcDest++ = c; } else if ((c == '\b') && (len > 0)) { pcDest--; len--; } else if (c == '\n') { *pcDest = 0; return pdPASS; } } return pdFAIL; } signed portBASE_TYPE xSerialGetChar(HANDLE xPort, char *pcRxedChar, portTickType xBlockTime) { USART_PORT *port = (USART_PORT*) xPort; assert(xPort != NULL); if (!(port->uiOpened)) return pdFAIL; if (xQueueReceive(port->xReciveQueue, pcRxedChar, xBlockTime) == pdPASS) { if (port->uiEcho) xSerialPutChar(xPort, *pcRxedChar, xBlockTime); return pdPASS; } return pdFAIL; } Код прерывания: void UART1_IrqHandler(void) { portBASE_TYPE xHigerPrioritTaskWoken = pdFALSE; prvSerialExchange(1, &xHigerPrioritTaskWoken); portEND_SWITCHING_ISR(xHigerPrioritTaskWoken); } void prvSerialExchange(uint32_t iPortIndex, portBASE_TYPE *xHigerPrioritTaskWoken) { portBASE_TYPE status; char cChar; // get status status = xSerial_ports[iPortIndex].xHwPort->US_CSR; if ((status & US_CSR_TXRDY) == US_CSR_TXRDY) { // transmit symbol if (xQueueReceiveFromISR(xSerial_ports[iPortIndex].xTransmitQueue, &cChar, xHigerPrioritTaskWoken) == pdTRUE) { xSerial_ports[iPortIndex].xHwPort->US_THR = cChar; // disable interrupt if nothing to send anymore if (xQueueIsQueueEmptyFromISR( xSerial_ports[iPortIndex].xTransmitQueue)) USART_DisableIt(xSerial_ports[iPortIndex].xHwPort, UART_IER_TXRDY); } } if ((status & US_CSR_RXRDY) == US_CSR_RXRDY) { // receive symbol cChar = xSerial_ports[iPortIndex].xHwPort->US_RHR; xQueueSendFromISR(xSerial_ports[iPortIndex].xReciveQueue, &cChar, xHigerPrioritTaskWoken); } } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sergeeff 1 15 апреля, 2011 Опубликовано 15 апреля, 2011 · Жалоба Утечки стека не бывает, бывает переполнение стека. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 63 15 апреля, 2011 Опубликовано 15 апреля, 2011 · Жалоба С приоритетом прерывания не напутали случайно? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
id_soft 0 16 апреля, 2011 Опубликовано 16 апреля, 2011 · Жалоба С приоритетом прерывания не напутали случайно? Да. Проверил приоритет прерывания USART. Он был выше чем у системных прерываний FreeRTOS. Исправил - все заработало. Спасибо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться