2009-11-30 17:03:37 +01:00
|
|
|
/**
|
|
|
|
******************************************************************************
|
|
|
|
*
|
|
|
|
* @file pios_com.c
|
2010-01-31 18:56:54 +01:00
|
|
|
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
|
|
|
* Parts by Thorsten Klose (tk@midibox.org) (tk@midibox.org)
|
2009-11-30 17:03:37 +01:00
|
|
|
* @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"
|
|
|
|
|
2010-02-28 07:47:49 +01:00
|
|
|
#if !defined(PIOS_DONT_USE_COM)
|
2009-11-30 17:03:37 +01:00
|
|
|
|
|
|
|
/* 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
|
|
|
|
*/
|
2009-12-08 03:13:21 +01:00
|
|
|
int32_t PIOS_COM_Init(void)
|
2009-11-30 17:03:37 +01:00
|
|
|
{
|
|
|
|
int32_t ret = 0;
|
|
|
|
|
|
|
|
/* Disable callback by default */
|
|
|
|
receive_callback_func = NULL;
|
|
|
|
|
|
|
|
/* If any COM assignment: */
|
2009-12-08 03:13:21 +01:00
|
|
|
PIOS_USART_Init();
|
2010-02-10 04:31:51 +01:00
|
|
|
PIOS_USB_HID_Init(0);
|
2009-11-30 17:03:37 +01:00
|
|
|
|
2010-01-23 18:31:14 +01:00
|
|
|
return ret;
|
2009-11-30 17:03:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sends a package over given port
|
2010-02-10 04:31:51 +01:00
|
|
|
* \param[in] port COM port (COM_DEBUG_UART, COM_GPS_UART, COM_TELEM_UART, COM_AUX_UART, COM_USB_HID)
|
2009-11-30 17:03:37 +01:00
|
|
|
* \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
|
|
|
|
*/
|
2009-12-08 03:13:21 +01:00
|
|
|
int32_t PIOS_COM_SendBufferNonBlocking(COMPortTypeDef port, uint8_t *buffer, uint16_t len)
|
2009-11-30 17:03:37 +01:00
|
|
|
{
|
|
|
|
/* Branch depending on selected port */
|
|
|
|
switch(port) {
|
2010-02-12 11:11:17 +01:00
|
|
|
case COM_DEBUG_USART:
|
2009-12-08 03:13:21 +01:00
|
|
|
return PIOS_USART_TxBufferPutMoreNonBlocking(COM_DEBUG_PORT, buffer, len);
|
2010-02-12 11:11:17 +01:00
|
|
|
case COM_GPS_USART:
|
2009-12-08 03:13:21 +01:00
|
|
|
return PIOS_USART_TxBufferPutMoreNonBlocking(GPS, buffer, len);
|
2010-02-12 11:11:17 +01:00
|
|
|
case COM_TELEM_USART:
|
2009-12-08 03:13:21 +01:00
|
|
|
return PIOS_USART_TxBufferPutMoreNonBlocking(TELEM, buffer, len);
|
2010-02-12 11:11:17 +01:00
|
|
|
case COM_AUX_USART:
|
2009-12-08 03:13:21 +01:00
|
|
|
return PIOS_USART_TxBufferPutMoreNonBlocking(AUX, buffer, len);
|
2010-02-10 04:31:51 +01:00
|
|
|
case COM_USB_HID:
|
|
|
|
return PIOS_USB_HID_TxBufferPutMoreNonBlocking(buffer, len);
|
2009-11-30 17:03:37 +01:00
|
|
|
default:
|
|
|
|
/* Invalid port */
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sends a package over given port
|
|
|
|
* (blocking function)
|
2010-02-10 04:31:51 +01:00
|
|
|
* \param[in] port COM port (COM_DEBUG_UART, COM_GPS_UART, COM_TELEM_UART, COM_AUX_UART, COM_USB_HID)
|
2009-11-30 17:03:37 +01:00
|
|
|
* \param[in] buffer character buffer
|
|
|
|
* \param[in] len buffer length
|
|
|
|
* \return -1 if port not available
|
|
|
|
* \return 0 on success
|
|
|
|
*/
|
2009-12-08 03:13:21 +01:00
|
|
|
int32_t PIOS_COM_SendBuffer(COMPortTypeDef port, uint8_t *buffer, uint16_t len)
|
2009-11-30 17:03:37 +01:00
|
|
|
{
|
|
|
|
/* Branch depending on selected port */
|
|
|
|
switch(port) {
|
2010-02-12 11:11:17 +01:00
|
|
|
case COM_DEBUG_USART:
|
2009-12-08 03:13:21 +01:00
|
|
|
return PIOS_USART_TxBufferPutMore(COM_DEBUG_PORT, buffer, len);
|
2010-02-12 11:11:17 +01:00
|
|
|
case COM_GPS_USART:
|
2009-12-08 03:13:21 +01:00
|
|
|
return PIOS_USART_TxBufferPutMore(GPS, buffer, len);
|
2010-02-12 11:11:17 +01:00
|
|
|
case COM_TELEM_USART:
|
2009-12-08 03:13:21 +01:00
|
|
|
return PIOS_USART_TxBufferPutMore(TELEM, buffer, len);
|
2010-02-12 11:11:17 +01:00
|
|
|
case COM_AUX_USART:
|
2009-12-08 03:13:21 +01:00
|
|
|
return PIOS_USART_TxBufferPutMore(AUX, buffer, len);
|
2010-02-10 04:31:51 +01:00
|
|
|
case COM_USB_HID:
|
|
|
|
return PIOS_USB_HID_TxBufferPutMore(buffer, len);
|
2009-11-30 17:03:37 +01:00
|
|
|
default:
|
|
|
|
/* Invalid port */
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sends a single character over given port
|
2010-02-10 04:31:51 +01:00
|
|
|
* \param[in] port COM port (COM_DEBUG_UART, COM_GPS_UART, COM_TELEM_UART, COM_AUX_UART, COM_USB_HID)
|
2009-11-30 17:03:37 +01:00
|
|
|
* \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
|
|
|
|
*/
|
2009-12-08 03:13:21 +01:00
|
|
|
int32_t PIOS_COM_SendCharNonBlocking(COMPortTypeDef port, char c)
|
2009-11-30 17:03:37 +01:00
|
|
|
{
|
2009-12-08 03:13:21 +01:00
|
|
|
return PIOS_COM_SendBufferNonBlocking(port, (uint8_t *)&c, 1);
|
2009-11-30 17:03:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sends a single character over given port
|
|
|
|
* (blocking function)
|
2010-02-10 04:31:51 +01:00
|
|
|
* \param[in] port COM port (COM_DEBUG_UART, COM_GPS_UART, COM_TELEM_UART, COM_AUX_UART, COM_USB_HID)
|
2009-11-30 17:03:37 +01:00
|
|
|
* \param[in] c character
|
|
|
|
* \return -1 if port not available
|
|
|
|
* \return 0 on success
|
|
|
|
*/
|
2009-12-08 03:13:21 +01:00
|
|
|
int32_t PIOS_COM_SendChar(COMPortTypeDef port, char c)
|
2009-11-30 17:03:37 +01:00
|
|
|
{
|
2009-12-08 03:13:21 +01:00
|
|
|
return PIOS_COM_SendBuffer(port, (uint8_t *)&c, 1);
|
2009-11-30 17:03:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sends a string over given port
|
2010-02-10 04:31:51 +01:00
|
|
|
* \param[in] port COM port (COM_DEBUG_UART, COM_GPS_UART, COM_TELEM_UART, COM_AUX_UART, COM_USB_HID)
|
2009-11-30 17:03:37 +01:00
|
|
|
* \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
|
|
|
|
*/
|
2009-12-08 03:13:21 +01:00
|
|
|
int32_t PIOS_COM_SendStringNonBlocking(COMPortTypeDef port, char *str)
|
2009-11-30 17:03:37 +01:00
|
|
|
{
|
2009-12-08 03:13:21 +01:00
|
|
|
return PIOS_COM_SendBufferNonBlocking(port, (uint8_t *)str, (uint16_t)strlen(str));
|
2009-11-30 17:03:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sends a string over given port
|
|
|
|
* (blocking function)
|
2010-02-10 04:31:51 +01:00
|
|
|
* \param[in] port COM port (COM_DEBUG_UART, COM_GPS_UART, COM_TELEM_UART, COM_AUX_UART, COM_USB_HID)
|
2009-11-30 17:03:37 +01:00
|
|
|
* \param[in] str zero-terminated string
|
|
|
|
* \return -1 if port not available
|
|
|
|
* \return 0 on success
|
|
|
|
*/
|
2009-12-08 03:13:21 +01:00
|
|
|
int32_t PIOS_COM_SendString(COMPortTypeDef port, char *str)
|
2009-11-30 17:03:37 +01:00
|
|
|
{
|
2009-12-08 03:13:21 +01:00
|
|
|
return PIOS_COM_SendBuffer(port, (uint8_t *)str, strlen(str));
|
2009-11-30 17:03:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sends a formatted string (-> printf) over given port
|
2010-02-10 04:31:51 +01:00
|
|
|
* \param[in] port COM port (COM_DEBUG_UART, COM_GPS_UART, COM_TELEM_UART, COM_AUX_UART, COM_USB_HID)
|
2009-11-30 17:03:37 +01:00
|
|
|
* \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
|
|
|
|
*/
|
2009-12-08 03:13:21 +01:00
|
|
|
int32_t PIOS_COM_SendFormattedStringNonBlocking(COMPortTypeDef port, char *format, ...)
|
2009-11-30 17:03:37 +01:00
|
|
|
{
|
|
|
|
uint8_t buffer[128]; // TODO: tmp!!! Provide a streamed COM method later!
|
2009-11-30 18:01:21 +01:00
|
|
|
|
2009-11-30 17:03:37 +01:00
|
|
|
va_list args;
|
|
|
|
|
|
|
|
va_start(args, format);
|
|
|
|
vsprintf((char *)buffer, format, args);
|
2009-12-08 03:13:21 +01:00
|
|
|
return PIOS_COM_SendBufferNonBlocking(port, buffer, (uint16_t)strlen((char *)buffer));
|
2009-11-30 17:03:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sends a formatted string (-> printf) over given port
|
|
|
|
* (blocking function)
|
2010-02-10 04:31:51 +01:00
|
|
|
* \param[in] port COM port (COM_DEBUG_UART, COM_GPS_UART, COM_TELEM_UART, COM_AUX_UART, COM_USB_HID)
|
2009-11-30 17:03:37 +01:00
|
|
|
* \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
|
|
|
|
*/
|
2009-12-08 03:13:21 +01:00
|
|
|
int32_t PIOS_COM_SendFormattedString(COMPortTypeDef port, char *format, ...)
|
2009-11-30 17:03:37 +01:00
|
|
|
{
|
|
|
|
uint8_t buffer[128]; // TODO: tmp!!! Provide a streamed COM method later!
|
|
|
|
va_list args;
|
|
|
|
|
|
|
|
va_start(args, format);
|
|
|
|
vsprintf((char *)buffer, format, args);
|
2009-12-08 03:13:21 +01:00
|
|
|
return PIOS_COM_SendBuffer(port, buffer, (uint16_t)strlen((char *)buffer));
|
2009-11-30 17:03:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks for incoming COM messages, calls the callback function which has
|
2010-01-25 16:23:55 +01:00
|
|
|
* been installed via PIOS_COM_ReceiveCallbackInit()
|
2009-11-30 17:03:37 +01:00
|
|
|
*
|
|
|
|
* Not for use in an application - this function is called by
|
|
|
|
* by a task in the programming model!
|
|
|
|
*
|
|
|
|
* \return < 0 on errors
|
|
|
|
*/
|
2009-12-08 03:13:21 +01:00
|
|
|
int32_t PIOS_COM_ReceiveHandler(void)
|
2009-11-30 17:03:37 +01:00
|
|
|
{
|
|
|
|
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 {
|
2010-02-10 04:31:51 +01:00
|
|
|
/* 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 ;) */
|
2009-11-30 17:03:37 +01:00
|
|
|
int32_t status = -1;
|
2010-02-10 04:31:51 +01:00
|
|
|
switch(intf++) {
|
2010-02-12 11:11:17 +01:00
|
|
|
case COM_DEBUG_USART:
|
2010-02-10 04:31:51 +01:00
|
|
|
status = PIOS_USART_RxBufferGet(COM_DEBUG_PORT);
|
2010-02-12 11:11:17 +01:00
|
|
|
port = COM_DEBUG_USART;
|
2010-02-10 04:31:51 +01:00
|
|
|
break;
|
2010-02-12 11:11:17 +01:00
|
|
|
case COM_GPS_USART:
|
2010-02-10 04:31:51 +01:00
|
|
|
status = PIOS_USART_RxBufferGet(GPS);
|
2010-02-12 11:11:17 +01:00
|
|
|
port = COM_GPS_USART;
|
2010-02-10 04:31:51 +01:00
|
|
|
break;
|
2010-02-12 11:11:17 +01:00
|
|
|
case COM_TELEM_USART:
|
2010-02-10 04:31:51 +01:00
|
|
|
status = PIOS_USART_RxBufferGet(TELEM);
|
2010-02-12 11:11:17 +01:00
|
|
|
port = COM_TELEM_USART;
|
2010-02-10 04:31:51 +01:00
|
|
|
break;
|
2010-02-12 11:11:17 +01:00
|
|
|
case COM_AUX_USART:
|
2010-02-10 04:31:51 +01:00
|
|
|
status = PIOS_USART_RxBufferGet(AUX);
|
2010-02-12 11:11:17 +01:00
|
|
|
port = COM_AUX_USART;
|
2010-02-10 04:31:51 +01:00
|
|
|
break;
|
|
|
|
case COM_USB_HID:
|
|
|
|
status = PIOS_USB_HID_RxBufferGet();
|
|
|
|
port = COM_USB_HID;
|
|
|
|
break;
|
2009-11-30 17:03:37 +01:00
|
|
|
default:
|
2010-02-10 04:31:51 +01:00
|
|
|
/* Allow 64 forwards maximum to yield some CPU time for other tasks */
|
2009-11-30 17:03:37 +01:00
|
|
|
if(bytes_forwarded && total_bytes_forwarded < 64) {
|
2010-02-10 04:31:51 +01:00
|
|
|
intf = 0; /* Restart at start */
|
|
|
|
bytes_forwarded = 0; /* Ror checking, if bytes still have been forwarded in next round */
|
2009-11-30 17:03:37 +01:00
|
|
|
} else {
|
2010-02-10 04:31:51 +01:00
|
|
|
again = 0; /* No more interfaces to be processed */
|
2009-11-30 17:03:37 +01:00
|
|
|
}
|
2010-02-10 04:31:51 +01:00
|
|
|
status = -1; /* Empty round - no message */
|
2009-11-30 17:03:37 +01:00
|
|
|
}
|
2010-02-10 04:31:51 +01:00
|
|
|
|
2009-11-30 17:03:37 +01:00
|
|
|
/* 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
|
2009-12-08 03:13:21 +01:00
|
|
|
* PIOS_COM_ReceiveCallbackInit(CONSOLE_Parse);
|
2009-11-30 17:03:37 +01:00
|
|
|
* \endcode
|
|
|
|
* \param[in] callback_debug_command the callback function (NULL disables the callback)
|
|
|
|
* \return < 0 on errors
|
|
|
|
*/
|
2009-12-08 03:13:21 +01:00
|
|
|
int32_t PIOS_COM_ReceiveCallbackInit(void *callback_receive)
|
2009-11-30 17:03:37 +01:00
|
|
|
{
|
|
|
|
receive_callback_func = callback_receive;
|
|
|
|
|
|
|
|
/* No error */
|
|
|
|
return 0;
|
|
|
|
}
|
2010-02-28 07:47:49 +01:00
|
|
|
|
|
|
|
#endif
|