diff --git a/flight/sys/pios.h b/flight/sys/pios.h index 6e60c0dee..4d13a56d9 100644 --- a/flight/sys/pios.h +++ b/flight/sys/pios.h @@ -51,8 +51,8 @@ #include #include #include +#include -//#include //#include //#include diff --git a/flight/sys/pios_board.h b/flight/sys/pios_board.h index 9569df446..82d951b79 100644 --- a/flight/sys/pios_board.h +++ b/flight/sys/pios_board.h @@ -112,7 +112,7 @@ #define AUX_UART_GPIO_PORT GPIOA #define AUX_UART_RX_PIN GPIO_Pin_10 #define AUX_UART_TX_PIN GPIO_Pin_9 -#define GPS_REMAP_FUNC { } +#define AUX_UART_REMAP_FUNC { } #define AUX_UART_IRQ_CHANNEL USART1_IRQn #define AUX_UART_IRQHANDLER_FUNC void USART1_IRQHandler(void) #define AUX_UART_CLK_FUNC RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE) diff --git a/flight/sys/pios_irq.c b/flight/sys/pios_irq.c new file mode 100644 index 000000000..0e14da013 --- /dev/null +++ b/flight/sys/pios_irq.c @@ -0,0 +1,84 @@ + +/** + * Project: OpenPilot + * + * @author The OpenPilot Team, http://www.openpilot.org, Copyright (C) 2009. + * + * @file pios_irq.c + * IRQ Enable/Disable routines + * + * @see The GNU Public License (GPL) + */ +/* + * 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" + +/* Local Variables */ +/* The nesting counter ensures, that interrupts won't be enabled so long nested functions disable them */ +static unsigned int nested_ctr; + +/* Stored priority level before IRQ has been disabled (important for co-existence with vPortEnterCritical) */ +static unsigned int prev_primask; + +/* Disables all interrupts (nested) */ +int IRQDisable(void) +{ + /* Get current priority if nested level == 0 */ + if(!nested_ctr) { + __asm volatile ( \ + " mrs %0, primask\n" \ + : "=r" (prev_primask) \ + ); + } + + /* disable interrupts */ + __asm volatile ( \ + " mov r0, #1 \n" \ + " msr primask, r0\n" \ + :::"r0" \ + ); + + ++nested_ctr; + + /* No error */ + return 0; +} + +/* Enables all interrupts (nested) */ +int IRQEnable(void) +{ + /* Check for nesting error */ + if(nested_ctr == 0) { + /* Nesting error */ + return -1; + } + + /* Decrease nesting level */ + --nested_ctr; + + /* Set back previous priority once nested level reached 0 again */ + if(nested_ctr == 0) { + __asm volatile ( \ + " msr primask, %0\n" \ + :: "r" (prev_primask) \ + ); + } + + /* No error */ + return 0; +} \ No newline at end of file diff --git a/flight/sys/pios_irq.h b/flight/sys/pios_irq.h new file mode 100644 index 000000000..d074ecc03 --- /dev/null +++ b/flight/sys/pios_irq.h @@ -0,0 +1,43 @@ + +/** + * Project: OpenPilot + * + * @author The OpenPilot Team, http://www.openpilot.org, Copyright (C) 2009. + * + * @file pios_irq.h + * IRQ functions header + * + * @see The GNU Public License (GPL) + */ +/* + * 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_IRQ_H +#define PIOS_IRQ_H + +/* Function Prototypes */ +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); + +#endif /* PIOS_IRQ_H */ diff --git a/flight/sys/pios_led.c b/flight/sys/pios_led.c index f0277ce97..e7125391e 100644 --- a/flight/sys/pios_led.c +++ b/flight/sys/pios_led.c @@ -45,17 +45,17 @@ void LED_INIT(void) } } -void LED_ON(Led_TypeDef LEDNum) +void LED_ON(LedTypeDef LEDNum) { LED_GPIO_PORT[LEDNum]->BSRR = LED_GPIO_PIN[LEDNum]; } -void LED_OFF(Led_TypeDef LEDNum) +void LED_OFF(LedTypeDef LEDNum) { LED_GPIO_PORT[LEDNum]->BRR = LED_GPIO_PIN[LEDNum]; } -void LED_TOGGLE(Led_TypeDef LEDNum) +void LED_TOGGLE(LedTypeDef LEDNum) { LED_GPIO_PORT[LEDNum]->ODR ^= LED_GPIO_PIN[LEDNum]; } diff --git a/flight/sys/pios_led.h b/flight/sys/pios_led.h index 2cc4c431a..c8de746eb 100644 --- a/flight/sys/pios_led.h +++ b/flight/sys/pios_led.h @@ -29,12 +29,12 @@ #define PIOS_LED_H /* Type Definitions */ -typedef enum {LED1 = 0, LED2 = 1} Led_TypeDef; +typedef enum {LED1 = 0, LED2 = 1} LedTypeDef; /* Exported Functions */ extern void LED_INIT(void); -extern void LED_ON(Led_TypeDef LEDNum); -extern void LED_OFF(Led_TypeDef LEDNum); -extern void LED_TOGGLE(Led_TypeDef LEDNum); +extern void LED_ON(LedTypeDef LEDNum); +extern void LED_OFF(LedTypeDef LEDNum); +extern void LED_TOGGLE(LedTypeDef LEDNum); #endif /* PIOS_LED_H */ diff --git a/flight/sys/pios_uart.c b/flight/sys/pios_uart.c index 6d84d87cd..e790f8917 100644 --- a/flight/sys/pios_uart.c +++ b/flight/sys/pios_uart.c @@ -170,3 +170,405 @@ void UARTChangeBaud(USART_TypeDef* USARTx, uint32_t Baud) /* Write to USART BRR */ USARTx->BRR = (uint16_t)tmpreg; } + +/*----------------------------------------------------------------------------------*/ +/* WORK IN PROGRESS BELOW */ +/*----------------------------------------------------------------------------------*/ + +///////////////////////////////////////////////////////////////////////////// +//! returns number of free bytes in receive buffer +//! \param[in] uart UART number (0..1) +//! \return uart number of free bytes +//! \return 1: uart available +//! \return 0: uart not available +///////////////////////////////////////////////////////////////////////////// +int UARTRxBufferFree(UARTNumTypeDef uart) +{ + if(uart >= UART_NUM) { + return 0; + } else { + return UART_RX_BUFFER_SIZE - rx_buffer_size[uart]; + } +} + +///////////////////////////////////////////////////////////////////////////// +//! returns number of used bytes in receive buffer +//! \param[in] uart UART number (0..1) +//! \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 +///////////////////////////////////////////////////////////////////////////// +int UARTRxBufferUsed(UARTNumTypeDef uart) +{ + if(uart >= UART_NUM) { + return 0; + } else { + return rx_buffer_size[uart]; + } +} + +///////////////////////////////////////////////////////////////////////////// +//! gets a byte from the receive buffer +//! \param[in] uart UART number (0..1) +//! \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 +///////////////////////////////////////////////////////////////////////////// +int UARTRxBufferGet(UARTNumTypeDef uart) +{ + + if(uart >= UART_NUM) { + /* UART not available */ + return -1; + } + if(!rx_buffer_size[uart]) { + /* nothing new in buffer */ + return -2; + } + + /* get byte - this operation should be atomic! */ + IRQDisable(); + u8 b = rx_buffer[uart][rx_buffer_tail[uart]]; + if(++rx_buffer_tail[uart] >= UART_RX_BUFFER_SIZE) { + rx_buffer_tail[uart] = 0; + } + --rx_buffer_size[uart]; + IRQEnable(); + + /* Return received byte */ + return b; +} + +///////////////////////////////////////////////////////////////////////////// +//! returns the next byte of the receive buffer without taking it +//! \param[in] uart UART number (0..1) +//! \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 +///////////////////////////////////////////////////////////////////////////// +int UARTRxBufferPeek(UARTNumTypeDef uart) +{ + if(uart >= UART_NUM) { + /* UART not available */ + return -1; + } + + if(!rx_buffer_size[uart]) { + /* Nothing new in buffer */ + return -2; + } + + /* Get byte - this operation should be atomic! */ + IRQDisable(); + uint8_t b = rx_buffer[uart][rx_buffer_tail[uart]]; + IRQEnable(); + + /* Return received byte */ + return b; +} + +///////////////////////////////////////////////////////////////////////////// +//! puts a byte onto the receive buffer +//! \param[in] uart UART number (0..1) +//! \param[in] b byte which should be put into Rx buffer +//! \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 +///////////////////////////////////////////////////////////////////////////// +int UARTRxBufferPut(UARTNumTypeDef uart, uint8_t b) +{ + if(uart >= UART_NUM) { + /* UART not available */ + return -1; + } + + if(rx_buffer_size[uart] >= UART_RX_BUFFER_SIZE) { + /* Buffer full (retry) */ + return -2; + } + + /* Copy received byte into receive buffer */ + /* This operation should be atomic! */ + IRQDisable(); + rx_buffer[uart][rx_buffer_head[uart]] = b; + if(++rx_buffer_head[uart] >= UART_RX_BUFFER_SIZE) { + rx_buffer_head[uart] = 0; + } + ++rx_buffer_size[uart]; + IRQEnable(); + + /* No error */ + return 0; +} + + +///////////////////////////////////////////////////////////////////////////// +//! returns number of free bytes in transmit buffer +//! \param[in] uart UART number (0..1) +//! \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 +///////////////////////////////////////////////////////////////////////////// +int UARTTxBufferFree(UARTNumTypeDef uart) +{ + if(uart >= UART_NUM) { + return 0; + } else { + return UART_TX_BUFFER_SIZE - tx_buffer_size[uart]; + } +} + +///////////////////////////////////////////////////////////////////////////// +//! returns number of used bytes in transmit buffer +//! \param[in] uart UART number (0..1) +//! \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 +///////////////////////////////////////////////////////////////////////////// +int UARTTxBufferUsed(UARTNumTypeDef uart) +{ + if(uart >= UART_NUM) { + return 0; + } else { + return tx_buffer_size[uart]; + } +} + +///////////////////////////////////////////////////////////////////////////// +//! gets a byte from the transmit buffer +//! \param[in] uart UART number (0..1) +//! \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 +///////////////////////////////////////////////////////////////////////////// +int UARTTxBufferGet(UARTNumTypeDef uart) +{ + if(uart >= UART_NUM) { + /* UART not available */ + return -1; + } + + if(!tx_buffer_size[uart]) { + /* Nothing new in buffer */ + return -2; + } + + /* Get byte - this operation should be atomic! */ + IRQDisable(); + uint8_t b = tx_buffer[uart][tx_buffer_tail[uart]]; + if(++tx_buffer_tail[uart] >= UART_TX_BUFFER_SIZE) { + tx_buffer_tail[uart] = 0; + } + --tx_buffer_size[uart]; + IRQEnable(); + + /* Return transmitted byte */ + return b; +} + +///////////////////////////////////////////////////////////////////////////// +//! puts more than one byte onto the transmit buffer (used for atomic sends) +//! \param[in] uart UART number (0..1) +//! \param[in] *buffer pointer to buffer to be sent +//! \param[in] len number of bytes to be sent +//! \return 0 if no error +//! \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 +///////////////////////////////////////////////////////////////////////////// +int UARTTxBufferPutMore_NonBlocking(UARTNumTypeDef uart, uint8_t *buffer, uint16_t len) +{ + if(uart >= UART_NUM) { + /* UART not available */ + return -1; + } + + if((tx_buffer_size[uart]+len) >= UART_TX_BUFFER_SIZE) { + /* Buffer full or cannot get all requested bytes (retry) */ + return -2; + } + + /* Copy bytes to be transmitted into transmit buffer */ + /* This operation should be atomic! */ + IRQDisable(); + + uint16_t i; + for(i = 0; i < len; ++i) { + tx_buffer[uart][tx_buffer_head[uart]] = *buffer++; + + if(++tx_buffer_head[uart] >= UART_TX_BUFFER_SIZE) { + tx_buffer_head[uart] = 0; + } + + /* Enable Tx interrupt if buffer was empty */ + if(++tx_buffer_size[uart] == 1) { + switch(uart) { + /* Enable TXE interrupt (TXEIE=1) */ + case 0: GPS_UART->CR1 |= (1 << 7); break; + /* Enable TXE interrupt (TXEIE=1) */ + case 1: TELEM_UART->CR1 |= (1 << 7); break; + /* Enable TXE interrupt (TXEIE=1) */ + case 2: AUX_UART_UART->CR1 |= (1 << 7); break; + /* Uart not supported by routine (yet) */ + default: IRQEnable(); return -3; + } + } + } + + IRQEnable(); + + /* No error */ + return 0; +} + +///////////////////////////////////////////////////////////////////////////// +//! puts more than one byte onto the transmit buffer (used for atomic sends)
+//! (blocking function) +//! \param[in] uart UART number (0..1) +//! \param[in] *buffer pointer to buffer to be sent +//! \param[in] len number of bytes to be sent +//! \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 +///////////////////////////////////////////////////////////////////////////// +int UARTTxBufferPutMore(UARTNumTypeDef uart, uint8_t *buffer, uint16_t len) +{ + int error; + + while((error = UARTTxBufferPutMore_NonBlocking(uart, buffer, len)) == -2); + + return error; +} + +///////////////////////////////////////////////////////////////////////////// +//! puts a byte onto the transmit buffer +//! \param[in] uart UART number (0..1) +//! \param[in] b byte which should be put into Tx buffer +//! \return 0 if no error +//! \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 +///////////////////////////////////////////////////////////////////////////// +int UARTTxBufferPut_NonBlocking(UARTNumTypeDef uart, uint8_t b) +{ + /* For more comfortable usage... */ + /* -> Just forward to MIOS32_UART_TxBufferPutMore */ + return UARTTxBufferPutMore(uart, &b, 1); +} + +///////////////////////////////////////////////////////////////////////////// +//! puts a byte onto the transmit buffer
+//! (blocking function) +//! \param[in] uart UART number (0..1) +//! \param[in] b byte which should be put into Tx buffer +//! \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 +///////////////////////////////////////////////////////////////////////////// +int UARTTxBufferPut(UARTNumTypeDef uart, uint8_t b) +{ + int error; + + while((error = UARTTxBufferPutMore(uart, &b, 1)) == -2); + + return error; +} + +/* Interrupt handler for GPS UART */ +GPS_IRQHANDLER_FUNC +{ + /* Check if RXNE flag is set */ + if(GPS_UART->SR & (1 << 5)) { + uint8_t b = GPS_UART->DR; + + int status = 0;//MIOS32_MIDI_SendByteToRxCallback(UART0, b); + + if(status == 0 && UARTRxBufferPut(0, b) < 0) { + /* Here we could add some error handling */ + } + } + + /* Check if TXE flag is set */ + if(GPS_UART->SR & (1 << 7)) { + if(UARTTxBufferUsed(0) > 0) { + int b = UARTTxBufferGet(0); + if( b < 0 ) { + /* Here we could add some error handling */ + GPS_UART->DR = 0xff; + } else { + GPS_UART->DR = b; + } + } else { + /* Disable TXE interrupt (TXEIE=0) */ + GPS_UART->CR1 &= ~(1 << 7); + } + } +} + +/* Interrupt handler for TELEM UART */ +TELEM_IRQHANDLER_FUNC +{ + /* check if RXNE flag is set */ + if(TELEM_UART->SR & (1 << 5)) { + uint8_t b = TELEM_UART->DR; + + int status = 0;//MIOS32_MIDI_SendByteToRxCallback(UART1, b); + + if(status == 0 && UARTRxBufferPut(1, b) < 0) { + /* Here we could add some error handling */ + } + } + + if(TELEM_UART->SR & (1 << 7)) { // check if TXE flag is set + if(UARTTxBufferUsed(1) > 0) { + int b = UARTTxBufferGet(1); + if(b < 0) { + /* Here we could add some error handling */ + TELEM_UART->DR = 0xff; + } else { + TELEM_UART->DR = b; + } + } else { + /* Disable TXE interrupt (TXEIE=0) */ + TELEM_UART->CR1 &= ~(1 << 7); + } + } +} + +/* Interrupt handler for AUX UART */ +AUX_UART_IRQHANDLER_FUNC +{ + /* check if RXNE flag is set */ + if(AUX_UART_UART->SR & (1 << 5)) { + uint8_t b = AUX_UART_UART->DR; + + int status = 0;//MIOS32_MIDI_SendByteToRxCallback(UART1, b); + + if(status == 0 && UARTRxBufferPut(1, b) < 0) { + /* Here we could add some error handling */ + } + } + + if(AUX_UART_UART->SR & (1 << 7)) { // check if TXE flag is set + if(UARTTxBufferUsed(1) > 0) { + int b = UARTTxBufferGet(1); + if(b < 0) { + /* Here we could add some error handling */ + AUX_UART_UART->DR = 0xff; + } else { + AUX_UART_UART->DR = b; + } + } else { + /* Disable TXE interrupt (TXEIE=0) */ + AUX_UART_UART->CR1 &= ~(1 << 7); + } + } +} \ No newline at end of file diff --git a/flight/sys/pios_uart.h b/flight/sys/pios_uart.h index 95030e604..0fb1bfe09 100644 --- a/flight/sys/pios_uart.h +++ b/flight/sys/pios_uart.h @@ -34,4 +34,22 @@ 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); +extern int UARTRxBufferPeek(UARTNumTypeDef uart); +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 UARTTxBufferPutMore(UARTNumTypeDef uart, uint8_t *buffer, uint16_t len); +extern int UARTTxBufferPut_NonBlocking(uint8_t uart, uint8_t b); +extern int UARTTxBufferPut(UARTNumTypeDef uart, uint8_t b); + #endif /* PIOS_UART_H */