diff --git a/flight/Makefile b/flight/Makefile index 7a613ba1c..324bedf69 100644 --- a/flight/Makefile +++ b/flight/Makefile @@ -85,6 +85,7 @@ SRC += $(SYSDIR)/pios_settings.c SRC += $(SYSDIR)/pios_led.c SRC += $(SYSDIR)/pios_uart.c SRC += $(SYSDIR)/pios_irq.c +SRC += $(SYSDIR)/pios_com.c ## CMSIS for STM32 SRC += $(CMSISDIR)/core_cm3.c diff --git a/flight/sys/pios.h b/flight/sys/pios.h index 7d83958c7..350f134d7 100644 --- a/flight/sys/pios.h +++ b/flight/sys/pios.h @@ -51,9 +51,7 @@ #include "pios_led.h" #include "pios_uart.h" #include "pios_irq.h" - -//#include "pios_spi.h" -//#include "pios_uart.h" +#include "pios_com.h" /* More added here as they get written */ diff --git a/flight/sys/pios_board.h b/flight/sys/pios_board.h index fb9773f08..613f35ea0 100644 --- a/flight/sys/pios_board.h +++ b/flight/sys/pios_board.h @@ -120,8 +120,9 @@ // USART Serial Ports //------------------------- #define UART_NUM 3 -#define UART_RX_BUFFER_SIZE 128 -#define UART_TX_BUFFER_SIZE 128 +#define UART_RX_BUFFER_SIZE 1024 +#define UART_TX_BUFFER_SIZE 256 +#define COM_DEBUG_PORT TELEM //------------------------- // Receiver PWM inputs diff --git a/flight/sys/pios_com.c b/flight/sys/pios_com.c new file mode 100644 index 000000000..c6f52935f --- /dev/null +++ b/flight/sys/pios_com.c @@ -0,0 +1,322 @@ +/** + ****************************************************************************** + * + * @file pios_com.c + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2009. + * @brief COM layer functions + * @see The GNU Public License (GPL) Version 3 + * @defgroup PIOS_COM COM layer functions + * @{ + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +/* Project Includes */ +#include "pios.h" + + +/* Private Function Prototypes */ + + +/* Local Variables */ +static int32_t (*receive_callback_func)(COMPortTypeDef port, char c); + + +/** +* Initializes COM layer +* \param[in] mode currently only mode 0 supported +* \return < 0 if initialisation failed +*/ +int32_t COMInit(void) +{ + int32_t ret = 0; + + /* Disable callback by default */ + receive_callback_func = NULL; + + /* If any COM assignment: */ + UARTInit(); + + return -ret; +} + + +/** +* This function checks the availability of a COM port +* \param[in] port COM port (COM_GPS_UART, COM_TELEM_UART, COM_AUX_UART) +* \return 1: port available +* \return 0: port not available +* \note Deprecated since our hardware is a constant +*/ +int32_t COMCheckAvailable(COMPortTypeDef port) +{ + /* Deprecated since our hardware is a constant */ +} + + +/** +* Sends a package over given port +* \param[in] port COM port (COM_GPS_UART, COM_TELEM_UART, COM_AUX_UART) +* \param[in] buffer character buffer +* \param[in] len buffer length +* \return -1 if port not available +* \return -2 if non-blocking mode activated: buffer is full +* caller should retry until buffer is free again +* \return 0 on success +*/ +int32_t COMSendBufferNonBlocking(COMPortTypeDef port, uint8_t *buffer, uint16_t len) +{ + /* Branch depending on selected port */ + switch(port) { + case 0: + return UARTTxBufferPutMoreNonBlocking(COM_DEBUG_PORT, buffer, len); + case 1: + return UARTTxBufferPutMoreNonBlocking(GPS, buffer, len); + case 2: + return UARTTxBufferPutMoreNonBlocking(TELEM, buffer, len); + case 3: + return UARTTxBufferPutMoreNonBlocking(AUX, buffer, len); + default: + /* Invalid port */ + return -1; + } +} + + + +/** +* Sends a package over given port +* (blocking function) +* \param[in] port COM port (COM_GPS_UART, COM_TELEM_UART, COM_AUX_UART) +* \param[in] buffer character buffer +* \param[in] len buffer length +* \return -1 if port not available +* \return 0 on success +*/ +int32_t COMSendBuffer(COMPortTypeDef port, uint8_t *buffer, uint16_t len) +{ + /* Branch depending on selected port */ + switch(port) { + case 0: + return UARTTxBufferPutMore(COM_DEBUG_PORT, buffer, len); + case 1: + return UARTTxBufferPutMore(GPS, buffer, len); + case 2: + return UARTTxBufferPutMore(TELEM, buffer, len); + case 3: + return UARTTxBufferPutMore(AUX, buffer, len); + default: + /* Invalid port */ + return -1; + } +} + + +/** +* Sends a single character over given port +* \param[in] port COM port (COM_GPS_UART, COM_TELEM_UART, COM_AUX_UART) +* \param[in] c character +* \return -1 if port not available +* \return -2 buffer is full +* caller should retry until buffer is free again +* \return 0 on success +*/ +int32_t COMSendCharNonBlocking(COMPortTypeDef port, char c) +{ + return COMSendBufferNonBlocking(port, (uint8_t *)&c, 1); +} + + +/** +* Sends a single character over given port +* (blocking function) +* \param[in] port COM port (COM_GPS_UART, COM_TELEM_UART, COM_AUX_UART) +* \param[in] c character +* \return -1 if port not available +* \return 0 on success +*/ +int32_t COMSendChar(COMPortTypeDef port, char c) +{ + return COMSendBuffer(port, (uint8_t *)&c, 1); +} + + +/** +* Sends a string over given port +* \param[in] port COM port (COM_GPS_UART, COM_TELEM_UART, COM_AUX_UART) +* \param[in] str zero-terminated string +* \return -1 if port not available +* \return -2 buffer is full +* caller should retry until buffer is free again +* \return 0 on success +*/ +int32_t COMSendString_NonBlocking(COMPortTypeDef port, char *str) +{ + return COMSendBufferNonBlocking(port, (uint8_t *)str, (uint16_t)strlen(str)); +} + + +/** +* Sends a string over given port +* (blocking function) +* \param[in] port COM port (COM_GPS_UART, COM_TELEM_UART, COM_AUX_UART) +* \param[in] str zero-terminated string +* \return -1 if port not available +* \return 0 on success +*/ +int32_t MIOS32_COM_SendString(COMPortTypeDef port, char *str) +{ + /* return COMSendBuffer(port, (uint8_t *)str, strlen(str)); */ +} + + +/** +* Sends a formatted string (-> printf) over given port +* \param[in] port COM port (COM_GPS_UART, COM_TELEM_UART, COM_AUX_UART) +* \param[in] *format zero-terminated format string - 128 characters supported maximum! +* \param[in] ... optional arguments, +* 128 characters supported maximum! +* \return -2 if non-blocking mode activated: buffer is full +* caller should retry until buffer is free again +* \return 0 on success +*/ +int32_t MIOS32_COM_SendFormattedStringNonBlocking(COMPortTypeDef port, char *format, ...) +{ + uint8_t buffer[128]; // TODO: tmp!!! Provide a streamed COM method later! + /* + va_list args; + + va_start(args, format); + vsprintf((char *)buffer, format, args); + return COMSendBufferNonBlocking(port, buffer, (uint16_t)strlen((char *)buffer)); + */ +} + + +/** +* Sends a formatted string (-> printf) over given port +* (blocking function) +* \param[in] port COM port (COM_GPS_UART, COM_TELEM_UART, COM_AUX_UART) +* \param[in] *format zero-terminated format string - 128 characters supported maximum! +* \param[in] ... optional arguments, +* \return -1 if port not available +* \return 0 on success +*/ +int32_t MIOS32_COM_SendFormattedString(COMPortTypeDef port, char *format, ...) +{ + uint8_t buffer[128]; // TODO: tmp!!! Provide a streamed COM method later! + /* + va_list args; + + va_start(args, format); + vsprintf((char *)buffer, format, args); + return COMSendBuffer(port, buffer, (uint16_t)strlen((char *)buffer)); + */ +} + + + +/** +* Checks for incoming COM messages, calls the callback function which has +* been installed via COMReceiveCallbackInit() +* +* Not for use in an application - this function is called by +* by a task in the programming model! +* +* \return < 0 on errors +*/ +int32_t COMReceiveHandler(void) +{ + uint8_t port; + + /* Interface to be checked */ + uint8_t intf = 0; + + /* Number of forwards - stop after 10 forwards to yield some CPU time for other tasks */ + uint8_t total_bytes_forwarded = 0; + + uint8_t bytes_forwarded = 0; + uint8_t again = 1; + + do { + // Round Robin + // TODO: maybe a list based approach would be better + // it would allow to add/remove interfaces dynamically + // this would also allow to give certain ports a higher priority (to add them multiple times to the list) + // it would also improve this spagetthi code ;) + int32_t status = -1; + switch( intf++ ) { + case 0: status = UARTRxBufferGet(COM_DEBUG_PORT); port = COM_DEBUG_UART; break; + case 1: status = UARTRxBufferGet(GPS); port = COM_GPS_UART; break; + case 2: status = UARTRxBufferGet(TELEM); port = COM_TELEM_UART; break; + case 3: status = UARTRxBufferGet(AUX); port = COM_AUX_UART; break; + default: + // allow 64 forwards maximum to yield some CPU time for other tasks + if(bytes_forwarded && total_bytes_forwarded < 64) { + intf = 0; // restart with USB + bytes_forwarded = 0; // for checking, if bytes still have been forwarded in next round + } else { + again = 0; // no more interfaces to be processed + } + status = -1; // empty round - no message + } + + /* Message received? */ + if(status >= 0) { + /* Notify that a package has been forwarded */ + ++bytes_forwarded; + ++total_bytes_forwarded; + + /* Call function */ + if(receive_callback_func != NULL) + receive_callback_func(port, (uint8_t)status); + } + } while(again); + + return 0; +} + + +/** +* Installs the callback function which is executed on incoming characters +* from a COM interface. +* +* Example: +* \code +* int32_t CONSOLE_Parse(COMPortTypeDef port, char c) +* { +* // Do Parsing here +* +* return 0; // no error +* } +* \endcode +* +* The callback function has been installed in an Init() function with: +* \code +* COMReceiveCallbackInit(CONSOLE_Parse); +* \endcode +* \param[in] callback_debug_command the callback function (NULL disables the callback) +* \return < 0 on errors +*/ +int32_t COMReceiveCallbackInit(void *callback_receive) +{ + receive_callback_func = callback_receive; + + /* No error */ + return 0; +} diff --git a/flight/sys/pios_com.h b/flight/sys/pios_com.h new file mode 100644 index 000000000..ec0cbba38 --- /dev/null +++ b/flight/sys/pios_com.h @@ -0,0 +1,54 @@ +/** + ****************************************************************************** + * + * @file pios_com.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2009. + * @brief COM layer functions header + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef PIOS_COM_H +#define PIOS_COM_H + +/* GLobal Types */ +typedef enum { + COM_DEBUG_UART = 0, + COM_GPS_UART = 1, + COM_TELEM_UART = 2, + COM_AUX_UART = 3 +} COMPortTypeDef; + +/* Public Functions */ +extern int32_t COMInit(void); + +extern int32_t COMCheckAvailable(COMPortTypeDef port); + +extern int32_t COMSendChar_NonBlocking(COMPortTypeDef port, char c); +extern int32_t COMSendChar(COMPortTypeDef port, char c); +extern int32_t COMSendBuffer_NonBlocking(COMPortTypeDef port, uint8_t *buffer, uint16_t len); +extern int32_t COMSendBuffer(COMPortTypeDef port, uint8_t *buffer, uint16_t len); +extern int32_t COMSendStringNonBlocking(COMPortTypeDef port, char *str); +extern int32_t COMSendString(COMPortTypeDef port, char *str); +extern int32_t COMSendFormattedStringNonBlocking(COMPortTypeDef port, char *format, ...); +extern int32_t COMSendFormattedString(COMPortTypeDef port, char *format, ...); + +extern int32_t COMReceiveHandler(void); +extern int32_t COMReceiveCallback_Init(void *callback_receive); + +#endif /* PIOS_COM_H */ diff --git a/flight/sys/pios_irq.h b/flight/sys/pios_irq.h index bfc5b2ee0..887217db5 100644 --- a/flight/sys/pios_irq.h +++ b/flight/sys/pios_irq.h @@ -27,14 +27,6 @@ #define PIOS_IRQ_H /* Public Functions */ -extern void UARTInit(void); -extern void EnableAuxUART(void); -extern void DisableAuxUART(void); -extern void UARTChangeBaud(USART_TypeDef* USARTx, uint32_t Baud); - -/*----------------------------------------------------------------------------------*/ -/* WORK IN PROGRESS BELOW */ -/*----------------------------------------------------------------------------------*/ extern int IRQDisable(void); extern int IRQEnable(void); diff --git a/flight/sys/pios_uart.c b/flight/sys/pios_uart.c index 7e74b5820..04831bff2 100644 --- a/flight/sys/pios_uart.c +++ b/flight/sys/pios_uart.c @@ -34,15 +34,15 @@ /* Local Variables */ -static u8 rx_buffer[UART_NUM][UART_RX_BUFFER_SIZE]; -static volatile u8 rx_buffer_tail[UART_NUM]; -static volatile u8 rx_buffer_head[UART_NUM]; -static volatile u8 rx_buffer_size[UART_NUM]; +static uint8_t rx_buffer[UART_NUM][UART_RX_BUFFER_SIZE]; +static volatile uint8_t rx_buffer_tail[UART_NUM]; +static volatile uint8_t rx_buffer_head[UART_NUM]; +static volatile uint8_t rx_buffer_size[UART_NUM]; -static u8 tx_buffer[UART_NUM][UART_TX_BUFFER_SIZE]; -static volatile u8 tx_buffer_tail[UART_NUM]; -static volatile u8 tx_buffer_head[UART_NUM]; -static volatile u8 tx_buffer_size[UART_NUM]; +static uint8_t tx_buffer[UART_NUM][UART_TX_BUFFER_SIZE]; +static volatile uint8_t tx_buffer_tail[UART_NUM]; +static volatile uint8_t tx_buffer_head[UART_NUM]; +static volatile uint8_t tx_buffer_size[UART_NUM]; /** @@ -192,11 +192,6 @@ void UARTChangeBaud(USART_TypeDef* USARTx, uint32_t Baud) USARTx->BRR = (uint16_t)TmpReg; } - -/*----------------------------------------------------------------------------------*/ -/* WORK IN PROGRESS BELOW */ -/*----------------------------------------------------------------------------------*/ - /** * Returns number of free bytes in receive buffer * \param[in] uart UART name (GPS, TELEM, AUX) @@ -218,7 +213,7 @@ int UARTRxBufferFree(UARTNumTypeDef uart) * \param[in] uart UART name (GPS, TELEM, AUX) * \return > 0: number of used bytes * \return 0 if uart not available -* \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions +* \note Applications shouldn't call these functions directly, instead please use \ref PIOS_COM layer functions */ int UARTRxBufferUsed(UARTNumTypeDef uart) { @@ -235,7 +230,7 @@ int UARTRxBufferUsed(UARTNumTypeDef uart) * \return -1 if UART not available * \return -2 if no new byte available * \return >= 0: number of received bytes -* \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions +* \note Applications shouldn't call these functions directly, instead please use \ref PIOS_COM layer functions */ int UARTRxBufferGet(UARTNumTypeDef uart) { @@ -267,7 +262,7 @@ int UARTRxBufferGet(UARTNumTypeDef uart) * \return -1 if UART not available * \return -2 if no new byte available * \return >= 0: number of received bytes -* \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions +* \note Applications shouldn't call these functions directly, instead please use \ref PIOS_COM layer functions */ int UARTRxBufferPeek(UARTNumTypeDef uart) { @@ -297,7 +292,7 @@ int UARTRxBufferPeek(UARTNumTypeDef uart) * \return 0 if no error * \return -1 if UART not available * \return -2 if buffer full (retry) -* \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions +* \note Applications shouldn't call these functions directly, instead please use \ref PIOS_COM layer functions */ int UARTRxBufferPut(UARTNumTypeDef uart, uint8_t b) { @@ -331,7 +326,7 @@ int UARTRxBufferPut(UARTNumTypeDef uart, uint8_t b) * \param[in] uart UART name (GPS, TELEM, AUX) * \return number of free bytes * \return 0 if uart not available -* \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions +* \note Applications shouldn't call these functions directly, instead please use \ref PIOS_COM layer functions */ int UARTTxBufferFree(UARTNumTypeDef uart) { @@ -347,7 +342,7 @@ int UARTTxBufferFree(UARTNumTypeDef uart) * \param[in] uart UART name (GPS, TELEM, AUX) * \return number of used bytes * \return 0 if uart not available -* \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions +* \note Applications shouldn't call these functions directly, instead please use \ref PIOS_COM layer functions */ int UARTTxBufferUsed(UARTNumTypeDef uart) { @@ -364,7 +359,7 @@ int UARTTxBufferUsed(UARTNumTypeDef uart) * \return -1 if UART not available * \return -2 if no new byte available * \return >= 0: transmitted byte -* \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions +* \note Applications shouldn't call these functions directly, instead please use \ref PIOS_COM layer functions */ int UARTTxBufferGet(UARTNumTypeDef uart) { @@ -400,9 +395,9 @@ int UARTTxBufferGet(UARTNumTypeDef uart) * \return -1 if UART not available * \return -2 if buffer full or cannot get all requested bytes (retry) * \return -3 if UART not supported by MIOS32_UART_TxBufferPut Routine -* \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions +* \note Applications shouldn't call these functions directly, instead please use \ref PIOS_COM layer functions */ -int UARTTxBufferPutMore_NonBlocking(UARTNumTypeDef uart, uint8_t *buffer, uint16_t len) +int UARTTxBufferPutMoreNonBlocking(UARTNumTypeDef uart, uint8_t *buffer, uint16_t len) { if(uart >= UART_NUM) { /* UART not available */ @@ -456,13 +451,13 @@ int UARTTxBufferPutMore_NonBlocking(UARTNumTypeDef uart, uint8_t *buffer, uint16 * \return 0 if no error * \return -1 if UART not available * \return -3 if UART not supported by MIOS32_UART_TxBufferPut Routine -* \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions +* \note Applications shouldn't call these functions directly, instead please use \ref PIOS_COM layer functions */ int UARTTxBufferPutMore(UARTNumTypeDef uart, uint8_t *buffer, uint16_t len) { int error; - while((error = UARTTxBufferPutMore_NonBlocking(uart, buffer, len)) == -2); + while((error = UARTTxBufferPutMoreNonBlocking(uart, buffer, len)) == -2); return error; } @@ -475,7 +470,7 @@ int UARTTxBufferPutMore(UARTNumTypeDef uart, uint8_t *buffer, uint16_t len) * \return -1 if UART not available * \return -2 if buffer full (retry) * \return -3 if UART not supported by MIOS32_UART_TxBufferPut Routine -* \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions +* \note Applications shouldn't call these functions directly, instead please use \ref PIOS_COM layer functions */ int UARTTxBufferPut_NonBlocking(UARTNumTypeDef uart, uint8_t b) { @@ -492,7 +487,7 @@ int UARTTxBufferPut_NonBlocking(UARTNumTypeDef uart, uint8_t b) * \return 0 if no error * \return -1 if UART not available * \return -3 if UART not supported by MIOS32_UART_TxBufferPut Routine -* \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions +* \note Applications shouldn't call these functions directly, instead please use \ref PIOS_COM layer functions */ int UARTTxBufferPut(UARTNumTypeDef uart, uint8_t b) { diff --git a/flight/sys/pios_uart.h b/flight/sys/pios_uart.h index 294c599b2..012230f29 100644 --- a/flight/sys/pios_uart.h +++ b/flight/sys/pios_uart.h @@ -26,17 +26,17 @@ #ifndef PIOS_UART_H #define PIOS_UART_H + +/* Global Types */ +typedef enum {GPS = 0, TELEM = 1, AUX = 2} UARTNumTypeDef; + + /* Public Functions */ extern void UARTInit(void); extern void EnableAuxUART(void); extern void DisableAuxUART(void); extern void UARTChangeBaud(USART_TypeDef* USARTx, uint32_t Baud); -/*----------------------------------------------------------------------------------*/ -/* WORK IN PROGRESS BELOW */ -/*----------------------------------------------------------------------------------*/ -typedef enum {GPS = 0, TELEM = 1, AUX = 2} UARTNumTypeDef; - extern int UARTRxBufferFree(UARTNumTypeDef uart); extern int UARTRxBufferUsed(UARTNumTypeDef uart); extern int UARTRxBufferGet(UARTNumTypeDef uart); @@ -45,9 +45,9 @@ extern int UARTRxBufferPut(UARTNumTypeDef uart, uint8_t b); extern int UARTTxBufferFree(UARTNumTypeDef uart); extern int UARTTxBufferGet(UARTNumTypeDef uart); -extern int UARTTxBufferPutMore_NonBlocking(UARTNumTypeDef uart, uint8_t *buffer, uint16_t len); +extern int UARTTxBufferPutMoreNonBlocking(UARTNumTypeDef uart, uint8_t *buffer, uint16_t len); extern int UARTTxBufferPutMore(UARTNumTypeDef uart, uint8_t *buffer, uint16_t len); -extern int UARTTxBufferPut_NonBlocking(uint8_t uart, uint8_t b); +extern int UARTTxBufferPutNonBlocking(uint8_t uart, uint8_t b); extern int UARTTxBufferPut(UARTNumTypeDef uart, uint8_t b); #endif /* PIOS_UART_H */