diff --git a/conf/autopilot/rotorcraft.makefile b/conf/autopilot/rotorcraft.makefile index e42d413483..f027256de4 100644 --- a/conf/autopilot/rotorcraft.makefile +++ b/conf/autopilot/rotorcraft.makefile @@ -92,6 +92,7 @@ endif # # Telemetry/Datalink # +ap.srcs += mcu_periph/uart.c ap.srcs += $(SRC_ARCH)/mcu_periph/uart_arch.c ap.CFLAGS += -DDOWNLINK -DDOWNLINK_TRANSPORT=PprzTransport ap.CFLAGS += -DDOWNLINK_DEVICE=$(MODEM_PORT) diff --git a/conf/autopilot/subsystems/fixedwing/autopilot.makefile b/conf/autopilot/subsystems/fixedwing/autopilot.makefile index 3a7b993420..657350bb5c 100644 --- a/conf/autopilot/subsystems/fixedwing/autopilot.makefile +++ b/conf/autopilot/subsystems/fixedwing/autopilot.makefile @@ -134,6 +134,7 @@ ns_srcs += $(SRC_ARCH)/sys_time_hw.c # UARTS # +ns_srcs += mcu_periph/uart.c ns_srcs += $(SRC_ARCH)/mcu_periph/uart_arch.c # diff --git a/sw/airborne/arch/lpc21/mcu_periph/uart_arch.c b/sw/airborne/arch/lpc21/mcu_periph/uart_arch.c index 55d8df8c52..cb667a1c99 100644 --- a/sw/airborne/arch/lpc21/mcu_periph/uart_arch.c +++ b/sw/airborne/arch/lpc21/mcu_periph/uart_arch.c @@ -29,27 +29,138 @@ #include "mcu_periph/uart.h" #include "armVIC.h" + +void uart_periph_init_param(struct uart_periph* p, uint16_t baud, uint8_t mode, uint8_t fmode, char * dev) { + + ((uartRegs_t *)(p->reg_addr))->ier = 0x00; // disable all interrupts + ((uartRegs_t *)(p->reg_addr))->iir; // clear interrupt ID + ((uartRegs_t *)(p->reg_addr))->rbr; // clear receive register + ((uartRegs_t *)(p->reg_addr))->lsr; // clear line status register + + // set the baudrate + ((uartRegs_t *)(p->reg_addr))->lcr = ULCR_DLAB_ENABLE; // select divisor latches + ((uartRegs_t *)(p->reg_addr))->dll = (uint8_t)baud; // set for baud low byte + ((uartRegs_t *)(p->reg_addr))->dlm = (uint8_t)(baud >> 8); // set for baud high byte + + // set the number of characters and other + // user specified operating parameters + ((uartRegs_t *)(p->reg_addr))->lcr = (mode & ~ULCR_DLAB_ENABLE); + ((uartRegs_t *)(p->reg_addr))->fcr = fmode; + +} + +void uart_transmit(struct uart_periph* p, uint8_t data ) { + uint16_t temp; + unsigned cpsr; + + temp = (p->tx_insert_idx + 1) % UART_TX_BUFFER_SIZE; + + if (temp == p->tx_extract_idx) + return; // no room + + cpsr = disableIRQ(); // disable global interrupts + ((uartRegs_t *)(p->reg_addr))->ier &= ~UIER_ETBEI; // disable TX interrupts + restoreIRQ(cpsr); // restore global interrupts + + // check if in process of sending data + if (p->tx_running) { + // add to queue + p->tx_buf[p->tx_insert_idx] = data; + p->tx_insert_idx = temp; + } else { + // set running flag and write to output register + p->tx_running = 1; + ((uartRegs_t *)(p->reg_addr))->thr = data; + } + + cpsr = disableIRQ(); // disable global interrupts + ((uartRegs_t *)(p->reg_addr))->ier |= UIER_ETBEI; // enable TX interrupts + restoreIRQ(cpsr); // restore global interrupts +} + +static inline void uart_ISR(struct uart_periph* p) +{ + uint8_t iid; + + // loop until not more interrupt sources + while (((iid = ((uartRegs_t *)(p->reg_addr))->iir) & UIIR_NO_INT) == 0) + { + // identify & process the highest priority interrupt + switch (iid & UIIR_ID_MASK) + { + case UIIR_RLS_INT: // Receive Line Status + ((uartRegs_t *)(p->reg_addr))->lsr; // read LSR to clear + break; + + case UIIR_CTI_INT: // Character Timeout Indicator + case UIIR_RDA_INT: // Receive Data Available + do + { + uint16_t temp; + + // calc next insert index & store character + temp = (p->rx_insert_idx + 1) % UART_RX_BUFFER_SIZE; + p->rx_buf[p->rx_insert_idx] = ((uartRegs_t *)(p->reg_addr))->rbr; + + // check for more room in queue + if (temp != p->rx_extract_idx) + p->rx_insert_idx = temp; // update insert index + } + while (((uartRegs_t *)(p->reg_addr))->lsr & ULSR_RDR); + + break; + + case UIIR_THRE_INT: // Transmit Holding Register Empty + while (((uartRegs_t *)(p->reg_addr))->lsr & ULSR_THRE) + { + // check if more data to send + if (p->tx_insert_idx != p->tx_extract_idx) + { + ((uartRegs_t *)(p->reg_addr))->thr = p->tx_buf[p->tx_extract_idx]; + p->tx_extract_idx++; + p->tx_extract_idx %= UART_TX_BUFFER_SIZE; + } + else + { + // no + p->tx_running = 0; // clear running flag + break; + } + } + + break; + + default: // Unknown + ((uartRegs_t *)(p->reg_addr))->lsr; + ((uartRegs_t *)(p->reg_addr))->rbr; + break; + } + } +} + #ifdef USE_UART0 #ifndef UART0_VIC_SLOT #define UART0_VIC_SLOT 5 #endif - void uart0_ISR(void) __attribute__((naked)); -uint8_t uart0_rx_buffer[UART0_RX_BUFFER_SIZE]; -uint16_t uart0_rx_insert_idx, uart0_rx_extract_idx; +void uart0_ISR(void) { + // perform proper ISR entry so thumb-interwork works properly + ISR_ENTRY(); -uint8_t uart0_tx_buffer[UART0_TX_BUFFER_SIZE]; -uint16_t uart0_tx_insert_idx, uart0_tx_extract_idx; -uint8_t uart0_tx_running; + uart_ISR(&uart0); -void uart0_init( void ) { - uart0_init_param(UART0_BAUD, UART_8N1, UART_FIFO_8); + VICVectAddr = 0x00000000; // clear this interrupt from the VIC + ISR_EXIT(); // recover registers and return } -void uart0_init_param( uint16_t baud, uint8_t mode, uint8_t fmode) { +void uart0_init( void ) { + + uart_periph_init(&uart0); + uart0.reg_addr = UART0_BASE; + #ifdef USE_UART0_RX_ONLY // only use the RX0 P0.1 pin, no TX PINSEL0 = (PINSEL0 & ~U0_PINMASK_RX) | U0_PINSEL_RX; @@ -58,20 +169,8 @@ void uart0_init_param( uint16_t baud, uint8_t mode, uint8_t fmode) { PINSEL0 = (PINSEL0 & ~U0_PINMASK) | U0_PINSEL; #endif - U0IER = 0x00; // disable all interrupts - U0IIR; // clear interrupt ID - U0RBR; // clear receive register - U0LSR; // clear line status register - - // set the baudrate - U0LCR = ULCR_DLAB_ENABLE; // select divisor latches - U0DLL = (uint8_t)baud; // set for baud low byte - U0DLM = (uint8_t)(baud >> 8); // set for baud high byte - - // set the number of characters and other - // user specified operating parameters - U0LCR = (mode & ~ULCR_DLAB_ENABLE); - U0FCR = fmode; + // initialize uart parameters + uart_periph_init_param(&uart0, UART0_BAUD, UART_8N1, UART_FIFO_8, ""); // initialize the interrupt vector VICIntSelect &= ~VIC_BIT(VIC_UART0); // UART0 selected as IRQ @@ -79,138 +178,12 @@ void uart0_init_param( uint16_t baud, uint8_t mode, uint8_t fmode) { _VIC_CNTL(UART0_VIC_SLOT) = VIC_ENABLE | VIC_UART0; _VIC_ADDR(UART0_VIC_SLOT) = (uint32_t)uart0_ISR; // address of the ISR - // initialize the transmit data queue - uart0_tx_extract_idx = 0; - uart0_tx_insert_idx = 0; - uart0_tx_running = 0; - - // initialize the receive data queue - uart0_rx_extract_idx = 0; - uart0_rx_insert_idx = 0; - // enable receiver interrupts U0IER = UIER_ERBFI; } -bool_t uart0_check_free_space( uint8_t len) { - int16_t space = uart0_tx_extract_idx - uart0_tx_insert_idx; - if (space <= 0) - space += UART0_TX_BUFFER_SIZE; - - return (uint16_t)(space - 1) >= len; -} - -void uart0_transmit( unsigned char data ) { - uint16_t temp; - unsigned cpsr; - - temp = (uart0_tx_insert_idx + 1) % UART0_TX_BUFFER_SIZE; - - if (temp == uart0_tx_extract_idx) - // return -1; // no room - return; // no room - - cpsr = disableIRQ(); // disable global interrupts - U0IER &= ~UIER_ETBEI; // disable TX interrupts - restoreIRQ(cpsr); // restore global interrupts - - // check if in process of sending data - if (uart0_tx_running) - { - // add to queue - uart0_tx_buffer[uart0_tx_insert_idx] = (uint8_t)data; - uart0_tx_insert_idx = temp; - } - else - { - // set running flag and write to output register - uart0_tx_running = 1; - U0THR = (uint8_t)data; - } - - cpsr = disableIRQ(); // disable global interrupts - U0IER |= UIER_ETBEI; // enable TX interrupts - restoreIRQ(cpsr); // restore global interrupts - // return (uint8_t)ch; -} - - -void uart0_ISR(void) -{ - uint8_t iid; - - // perform proper ISR entry so thumb-interwork works properly - ISR_ENTRY(); - - // loop until not more interrupt sources - while (((iid = U0IIR) & UIIR_NO_INT) == 0) - { - // identify & process the highest priority interrupt - switch (iid & UIIR_ID_MASK) - { - case UIIR_RLS_INT: // Receive Line Status - U0LSR; // read LSR to clear - break; - - case UIIR_CTI_INT: // Character Timeout Indicator - case UIIR_RDA_INT: // Receive Data Available - do - { - uint16_t temp; - - // calc next insert index & store character - temp = (uart0_rx_insert_idx + 1) % UART0_RX_BUFFER_SIZE; - uart0_rx_buffer[uart0_rx_insert_idx] = U0RBR; - - // check for more room in queue - if (temp != uart0_rx_extract_idx) - uart0_rx_insert_idx = temp; // update insert index - } - while (U0LSR & ULSR_RDR); - - break; - - case UIIR_THRE_INT: // Transmit Holding Register Empty - while (U0LSR & ULSR_THRE) - { - // check if more data to send - if (uart0_tx_insert_idx != uart0_tx_extract_idx) - { - U0THR = uart0_tx_buffer[uart0_tx_extract_idx]; - uart0_tx_extract_idx++; - uart0_tx_extract_idx %= UART0_TX_BUFFER_SIZE; - } - else - { - // no - uart0_tx_running = 0; // clear running flag - break; - } - } - - break; - - default: // Unknown - U0LSR; - U0RBR; - break; - } - } - - VICVectAddr = 0x00000000; // clear this interrupt from the VIC - ISR_EXIT(); // recover registers and return -} - #endif /* USE_UART0 */ -/* - * - * UART1 handling functions - those are pale copies of UART0 ones - * We should probably find a better way to make the code configurable - * for both uarts - * - */ - #ifdef USE_UART1 #ifndef UART1_VIC_SLOT @@ -219,27 +192,21 @@ void uart0_ISR(void) void uart1_ISR(void) __attribute__((naked)); -uint8_t uart1_rx_buffer[UART1_RX_BUFFER_SIZE]; -uint16_t uart1_rx_insert_idx, uart1_rx_extract_idx; +void uart1_ISR(void) { + // perform proper ISR entry so thumb-interwork works properly + ISR_ENTRY(); -uint8_t uart1_tx_buffer[UART1_TX_BUFFER_SIZE]; -uint16_t uart1_tx_insert_idx, uart1_tx_extract_idx; -uint8_t uart1_tx_running; + uart_ISR(&uart1); + + VICVectAddr = 0x00000000; // clear this interrupt from the VIC + ISR_EXIT(); // recover registers and return +} void uart1_init( void ) { - uart1_init_param(UART1_BAUD, UART_8N1, UART_FIFO_8); -} -bool_t uart1_check_free_space( uint8_t len) { - int16_t space = uart1_tx_extract_idx - uart1_tx_insert_idx; - if (space <= 0) - space += UART1_TX_BUFFER_SIZE; + uart_periph_init(&uart1); + uart1.reg_addr = UART1_BASE; - return (uint16_t)(space - 1) >= len; -} - - -void uart1_init_param( uint16_t baud, uint8_t mode, uint8_t fmode) { #ifdef USE_UART1_RX_ONLY // only use the RX1 P0.9 pin, no TX PINSEL0 = (PINSEL0 & ~U1_PINMASK_RX) | U1_PINSEL_RX; @@ -248,20 +215,7 @@ void uart1_init_param( uint16_t baud, uint8_t mode, uint8_t fmode) { PINSEL0 = (PINSEL0 & ~U1_PINMASK) | U1_PINSEL; #endif - U1IER = 0x00; // disable all interrupts - U1IIR; // clear interrupt ID - U1RBR; // clear receive register - U1LSR; // clear line status register - - // set the baudrate - U1LCR = ULCR_DLAB_ENABLE; // select divisor latches - U1DLL = (uint8_t)baud; // set for baud low byte - U1DLM = (uint8_t)(baud >> 8); // set for baud high byte - - // set the number of characters and other - // user specified operating parameters - U1LCR = (mode & ~ULCR_DLAB_ENABLE); - U1FCR = fmode; + uart_periph_init_param(&uart1, UART1_BAUD, UART_8N1, UART_FIFO_8, ""); // initialize the interrupt vector VICIntSelect &= ~VIC_BIT(VIC_UART1); // UART1 selected as IRQ @@ -269,122 +223,9 @@ void uart1_init_param( uint16_t baud, uint8_t mode, uint8_t fmode) { _VIC_CNTL(UART1_VIC_SLOT) = VIC_ENABLE | VIC_UART1; _VIC_ADDR(UART1_VIC_SLOT) = (uint32_t)uart1_ISR; // address of the ISR - // initialize the transmit data queue - uart1_tx_extract_idx = 0; - uart1_tx_insert_idx = 0; - uart1_tx_running = 0; - - // initialize the receive data queue - uart1_rx_extract_idx = 0; - uart1_rx_insert_idx = 0; - // enable receiver interrupts U1IER = UIER_ERBFI; } +#endif -void uart1_transmit( unsigned char data ) { - uint16_t temp; - unsigned cpsr; - - temp = (uart1_tx_insert_idx + 1) % UART1_TX_BUFFER_SIZE; - - if (temp == uart1_tx_extract_idx) - // return -1; // no room - return; // no room - - cpsr = disableIRQ(); // disable global interrupts - U1IER &= ~UIER_ETBEI; // disable TX interrupts - restoreIRQ(cpsr); // restore global interrupts - - // check if in process of sending data - if (uart1_tx_running) - { - // add to queue - uart1_tx_buffer[uart1_tx_insert_idx] = (uint8_t)data; - uart1_tx_insert_idx = temp; - } - else - { - // set running flag and write to output register - uart1_tx_running = 1; - U1THR = (uint8_t)data; - } - - cpsr = disableIRQ(); // disable global interrupts - U1IER |= UIER_ETBEI; // enable TX interrupts - restoreIRQ(cpsr); // restore global interrupts -} - - -void uart1_ISR(void) -{ - uint8_t iid; - - // perform proper ISR entry so thumb-interwork works properly - ISR_ENTRY(); - - // loop until not more interrupt sources - while (((iid = U1IIR) & UIIR_NO_INT) == 0) - { - // identify & process the highest priority interrupt - switch (iid & UIIR_ID_MASK) - { - case UIIR_RLS_INT: // Receive Line Status - U1LSR; // read LSR to clear - break; - - case UIIR_CTI_INT: // Character Timeout Indicator - case UIIR_RDA_INT: // Receive Data Available - do - { - uint16_t temp; - // calc next insert index & store character - temp = (uart1_rx_insert_idx + 1) % UART1_RX_BUFFER_SIZE; - uart1_rx_buffer[uart1_rx_insert_idx] = U1RBR; - - // check for more room in queue - if (temp != uart1_rx_extract_idx) - uart1_rx_insert_idx = temp; // update insert index - } - while (U1LSR & ULSR_RDR); - - break; - - case UIIR_THRE_INT: // Transmit Holding Register Empty - while (U1LSR & ULSR_THRE) - { - // check if more data to send - if (uart1_tx_insert_idx != uart1_tx_extract_idx) - { - U1THR = uart1_tx_buffer[uart1_tx_extract_idx]; - uart1_tx_extract_idx++; - uart1_tx_extract_idx %= UART1_TX_BUFFER_SIZE; - } - else - { - // no - uart1_tx_running = 0; // clear running flag - break; - } - } - - break; - - case UIIR_MS_INT: // MODEM Status - U1MSR; // read MSR to clear - break; - - default: // Unknown - U1LSR; - U1RBR; - U1MSR; - break; - } - } - - VICVectAddr = 0x00000000; // clear this interrupt from the VIC - ISR_EXIT(); // recover registers and return -} - -#endif /* USE_UART1 */ diff --git a/sw/airborne/arch/lpc21/mcu_periph/uart_arch.h b/sw/airborne/arch/lpc21/mcu_periph/uart_arch.h index fbc1c6c991..40cd39250b 100644 --- a/sw/airborne/arch/lpc21/mcu_periph/uart_arch.h +++ b/sw/airborne/arch/lpc21/mcu_periph/uart_arch.h @@ -29,11 +29,6 @@ #include "LPC21xx.h" #include BOARD_CONFIG -#define UART0_RX_BUFFER_SIZE 128 // UART0 receive buffer size -#define UART0_TX_BUFFER_SIZE 128 // UART0 transmit buffer size -#define UART1_RX_BUFFER_SIZE 128 // UART1 receive buffer size -#define UART1_TX_BUFFER_SIZE 128 // UART1 transmit buffer size - #define UART_BAUD(baud) (uint16_t)((PCLK / ((baud) * 16.0)) + 0.5) #define B1200 UART_BAUD(1200) @@ -64,33 +59,4 @@ #define UART_FIFO_8 (uint8_t)(UFCR_FIFO_ENABLE + UFCR_FIFO_TRIG8) #define UART_FIFO_14 (uint8_t)(UFCR_FIFO_ENABLE + UFCR_FIFO_TRIG14) - -extern uint16_t uart0_rx_insert_idx, uart0_rx_extract_idx; -extern uint8_t uart0_rx_buffer[UART0_RX_BUFFER_SIZE]; - -#define Uart0ChAvailable() (uart0_rx_insert_idx != uart0_rx_extract_idx) - -#define Uart0Getch() ({\ - uint8_t ret = uart0_rx_buffer[uart0_rx_extract_idx]; \ - uart0_rx_extract_idx = (uart0_rx_extract_idx + 1)%UART0_RX_BUFFER_SIZE; \ - ret; \ -}) - - -extern uint16_t uart1_rx_insert_idx, uart1_rx_extract_idx; -extern uint8_t uart1_rx_buffer[UART1_RX_BUFFER_SIZE]; -extern void uart1_init_param( uint16_t baud, uint8_t mode, uint8_t fmode); -extern void uart0_init_param( uint16_t baud, uint8_t mode, uint8_t fmode); - -#define Uart1ChAvailable() (uart1_rx_insert_idx != uart1_rx_extract_idx) - -#define Uart1Getch() ({\ - uint8_t ret = uart1_rx_buffer[uart1_rx_extract_idx]; \ - uart1_rx_extract_idx = (uart1_rx_extract_idx + 1)%UART1_RX_BUFFER_SIZE; \ - ret; \ -}) - -extern uint8_t uart0_tx_running; -extern uint8_t uart1_tx_running; - #endif /* LPC21_UART_ARCH_H */ diff --git a/sw/airborne/arch/omap/mcu_periph/uart_arch.c b/sw/airborne/arch/omap/mcu_periph/uart_arch.c new file mode 100644 index 0000000000..80297d57a2 --- /dev/null +++ b/sw/airborne/arch/omap/mcu_periph/uart_arch.c @@ -0,0 +1,128 @@ +/* + * Paparazzi $Id$ + * + * Copyright (C) 2009 Antoine Drouin + * + * This file is part of paparazzi. + * + * paparazzi 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 2, or (at your option) + * any later version. + * + * paparazzi 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 paparazzi; see the file COPYING. If not, write to + * the Free Software Foundation, 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "mcu_periph/uart.h" + +#include +#include +#include +#include +#include + +#include "fms/fms_serial_port.h" + + +void uart_periph_init_param(struct uart_periph* p, uint16_t baud, uint8_t mode, uint8_t fmode, char * dev) { + struct FmsSerialPort* fmssp; + // close serial port if already open + if (p->reg_addr != NULL) { + fmssp = (struct FmsSerialPort*)(p->reg_addr); + serial_port_close(fmssp); + serial_port_free(fmssp); + } + // open serial port + fmssp = serial_port_new(); + // use register address to store SerialPort structure pointer... + p->reg_addr = (void*)fmssp; + + //TODO: set device name in application and pass as argument + printf("opening %s on uart0 at %d\n",dev,baud); + serial_port_open_raw(fmssp,dev,baud); +} + +void uart_transmit(struct uart_periph* p, uint8_t data ) { + uint16_t temp = (p->tx_insert_idx + 1) % UART_TX_BUFFER_SIZE; + + if (temp == p->tx_extract_idx) + return; // no room + + // check if in process of sending data + if (p->tx_running) { // yes, add to queue + p->tx_buf[p->tx_insert_idx] = data; + p->tx_insert_idx = temp; + } + else { // no, set running flag and write to output register + p->tx_running = TRUE; + struct FmsSerialPort* fmssp = (struct FmsSerialPort*)(p->reg_addr); + write((int)(fmssp->fd),&data,1); + //printf("w %x\n",data); + } +} + +static inline void uart_handler(struct uart_periph* p) { + unsigned char c='D'; + + if (p->reg_addr == NULL) return; // device not initialized ? + + struct FmsSerialPort* fmssp = (struct FmsSerialPort*)(p->reg_addr); + int fd = fmssp->fd; + + // check if more data to send + if (p->tx_insert_idx != p->tx_extract_idx) { + write(fd,&(p->tx_buf[p->tx_extract_idx]),1); + //printf("w %x\n",p->tx_buf[p->tx_extract_idx]); + p->tx_extract_idx++; + p->tx_extract_idx %= UART_TX_BUFFER_SIZE; + } + else { + p->tx_running = FALSE; // clear running flag + } + + if(read(fd,&c,1) > 0){ + //printf("r %x %c\n",c,c); + uint16_t temp = (p->rx_insert_idx + 1) % UART_RX_BUFFER_SIZE; + p->rx_buf[p->rx_insert_idx] = c; + // check for more room in queue + if (temp != p->rx_extract_idx) + p->rx_insert_idx = temp; // update insert index + } + +} + +#ifdef USE_UART0 + +void uart0_init( void ) { + uart_periph_init(&uart0); + uart_periph_init_param(&uart0,UART0_BAUD,NULL,NULL,UART0_DEV); +} + + +void uart0_handler(void) { + uart_handler(&uart0); +} + +#endif /* USE_UART0 */ + +#ifdef USE_UART1 + +void uart1_init( void ) { + uart_periph_init(&uart1); + uart_periph_init_param(&uart1,UART1_BAUD,NULL,NULL,UART1_DEV); +} + +void uart1_handler(void) { + uart_handler(&uart1); +} + +#endif /* USE_UART1 */ + diff --git a/sw/airborne/arch/omap/mcu_periph/uart_arch.h b/sw/airborne/arch/omap/mcu_periph/uart_arch.h new file mode 100644 index 0000000000..98f70de300 --- /dev/null +++ b/sw/airborne/arch/omap/mcu_periph/uart_arch.h @@ -0,0 +1,72 @@ +/* + * $Id$ + * + * Copyright (C) 2009 Antoine Drouin + * + * This file is part of paparazzi. + * + * paparazzi 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 2, or (at your option) + * any later version. + * + * paparazzi 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 paparazzi; see the file COPYING. If not, write to + * the Free Software Foundation, 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef UART_ARCH_H +#define UART_ARCH_H + +#include "std.h" +//coment to avoid redefinition +/*#define B9600 9600 +#define B38400 38400 + #define B57600 57600 +#define B115200 115200 +*/ + +//junk for gps_configure_uart in gps_ubx.c to compile +#define UART_8N1 1 +#define UART_FIFO_8 1 +#define UART_BAUD(baud) (baud) + + +#define Uart1_init uart1_init() +#define Uart2_init uart2_init() +#define Uart3_init uart3_init() +#define Uart5_init uart5_init() + +#define UART1_irq_handler usart1_irq_handler +#define UART2_irq_handler usart2_irq_handler +#define UART3_irq_handler usart3_irq_handler +#define UART5_irq_handler usart5_irq_handler + +#if defined USE_UART0 || OVERRIDE_UART0_IRQ_HANDLER +extern void uart0_handler(void); +#endif + +#ifdef USE_UART0 + +void uart0_init( void ); + +#endif /* USE_UART0 */ + + +#if defined USE_UART1 || OVERRIDE_UART1_IRQ_HANDLER +extern void uart1_handler(void); +#endif + +#ifdef USE_UART1 + +void uart1_init( void ); + +#endif /* USE_UART1 */ + +#endif /* UART_ARCH_H */ diff --git a/sw/airborne/mcu_periph/uart.c b/sw/airborne/mcu_periph/uart.c new file mode 100644 index 0000000000..c17d790835 --- /dev/null +++ b/sw/airborne/mcu_periph/uart.c @@ -0,0 +1,57 @@ +/* + * Paparazzi $Id$ + * + * Copyright (C) 2010 The Paparazzi Team + * + * This file is part of paparazzi. + * + * paparazzi 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 2, or (at your option) + * any later version. + * + * paparazzi 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 paparazzi; see the file COPYING. If not, write to + * the Free Software Foundation, 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include "mcu_periph/uart.h" + +#ifdef USE_UART0 +struct uart_periph uart0; +#endif + +#ifdef USE_UART1 +struct uart_periph uart1; +#endif + +#ifdef USE_UART2 +struct uart_periph uart2; +#endif + +#ifdef USE_UART3 +struct uart_periph uart3; +#endif + +void uart_periph_init(struct uart_periph* p) { + p->rx_insert_idx = 0; + p->rx_extract_idx = 0; + p->tx_insert_idx = 0; + p->tx_extract_idx = 0; + p->tx_running = FALSE; +} + +bool_t uart_check_free_space(struct uart_periph* p, uint8_t len) { + int16_t space = p->tx_extract_idx - p->tx_insert_idx; + if (space <= 0) + space += UART_TX_BUFFER_SIZE; + return (uint16_t)(space - 1) >= len; +} + diff --git a/sw/airborne/mcu_periph/uart.h b/sw/airborne/mcu_periph/uart.h index 32bc3588d2..96a8bb9bb8 100644 --- a/sw/airborne/mcu_periph/uart.h +++ b/sw/airborne/mcu_periph/uart.h @@ -33,22 +33,53 @@ #include "mcu_periph/uart_arch.h" #include "std.h" +#define UART_RX_BUFFER_SIZE 128 +#define UART_TX_BUFFER_SIZE 128 + +/** + * UART peripheral + */ +struct uart_periph { + /* Receive buffer */ + uint8_t rx_buf[UART_RX_BUFFER_SIZE]; + uint16_t rx_insert_idx; + uint16_t rx_extract_idx; + /* Transmit buffer */ + uint8_t tx_buf[UART_RX_BUFFER_SIZE]; + uint16_t tx_insert_idx; + uint16_t tx_extract_idx; + uint8_t tx_running; + /* UART Register */ + void* reg_addr; +}; + +extern void uart_periph_init(struct uart_periph* p); +extern void uart_periph_init_param(struct uart_periph* p, uint16_t baud, uint8_t mode, uint8_t fmode, char * dev); +extern void uart_transmit(struct uart_periph* p, uint8_t data); +extern bool_t uart_check_free_space(struct uart_periph* p, uint8_t len); + +#define UartChAvailable(_p) (_p.rx_insert_idx != _p.rx_extract_idx) + +#define UartGetch(_p) ({ \ + uint8_t ret = _p.rx_buf[_p.rx_extract_idx]; \ + _p.rx_extract_idx = (_p.rx_extract_idx + 1)%UART_RX_BUFFER_SIZE; \ + ret; \ +}) + #ifdef USE_UART0 +extern struct uart_periph uart0; +extern void uart0_init(void); -extern void uart0_init( void ); -extern void uart0_transmit( uint8_t data ); -extern bool_t uart0_check_free_space( uint8_t len); - -#define Uart0Init uart0_init -#define Uart0CheckFreeSpace(_x) uart0_check_free_space(_x) -#define Uart0Transmit(_x) uart0_transmit(_x) +#define Uart0Init() uart_periph_init(&uart0) +#define Uart0CheckFreeSpace(_x) uart_check_free_space(&uart0, _x) +#define Uart0Transmit(_x) uart_transmit(&uart0, _x) #define Uart0SendMessage() {} +#define Uart0ChAvailable() UartChAvailable(uart0) +#define Uart0Getch() UartGetch(uart0) +#define Uart0TxRunning uart0.tx_running +#define Uart0InitParam(_b, _m, _fm) uart_periph_init_param(&uart0, _b, _m, _fm, "") -#define Uart0TxRunning uart0_tx_running -#define Uart0InitParam uart0_init_param - -/* I want to trigger USE_UART and generate macros with the makefile same variable */ #define UART0Init Uart0Init #define UART0CheckFreeSpace Uart0CheckFreeSpace #define UART0Transmit Uart0Transmit @@ -56,21 +87,20 @@ extern bool_t uart0_check_free_space( uint8_t len); #define UART0ChAvailable Uart0ChAvailable #define UART0Getch Uart0Getch -#endif /* USE_UART0 */ +#endif // USE_UART0 #ifdef USE_UART1 +extern struct uart_periph uart1; +extern void uart1_init(void); -extern void uart1_init( void ); -extern void uart1_transmit( uint8_t data ); -extern bool_t uart1_check_free_space( uint8_t len); - -#define Uart1Init uart1_init -#define Uart1CheckFreeSpace(_x) uart1_check_free_space(_x) -#define Uart1Transmit(_x) uart1_transmit(_x) +#define Uart1Init() uart_periph_init(&uart1) +#define Uart1CheckFreeSpace(_x) uart_check_free_space(&uart1, _x) +#define Uart1Transmit(_x) uart_transmit(&uart1, _x) #define Uart1SendMessage() {} - -#define Uart1TxRunning uart1_tx_running -#define Uart1InitParam uart1_init_param +#define Uart1ChAvailable() UartChAvailable(uart1) +#define Uart1Getch() UartGetch(uart1) +#define Uart1TxRunning uart1.tx_running +#define Uart1InitParam(_b, _m, _fm) uart_periph_init_param(&uart1, _b, _m, _fm, "") #define UART1Init Uart1Init #define UART1CheckFreeSpace Uart1CheckFreeSpace @@ -79,18 +109,20 @@ extern bool_t uart1_check_free_space( uint8_t len); #define UART1ChAvailable Uart1ChAvailable #define UART1Getch Uart1Getch -#endif /* USE_UART1 */ +#endif // USE_UART1 #ifdef USE_UART2 +extern struct uart_periph uart2; +extern void uart2_init(void); -extern void uart2_init( void ); -extern void uart2_transmit( uint8_t data ); -extern bool_t uart2_check_free_space( uint8_t len); - -#define Uart2Init uart2_init -#define Uart2CheckFreeSpace(_x) uart2_check_free_space(_x) -#define Uart2Transmit(_x) uart2_transmit(_x) +#define Uart2Init() uart_periph_init(&uart2) +#define Uart2CheckFreeSpace(_x) uart_check_free_space(&uart2, _x) +#define Uart2Transmit(_x) uart_transmit(&uart2, _x) #define Uart2SendMessage() {} +#define Uart2ChAvailable() UartChAvailable(uart2) +#define Uart2Getch() UartGetch(uart2) +#define Uart2TxRunning uart2.tx_running +#define Uart2InitParam(_b, _m, _fm) uart_periph_init_param(&uart2, _b, _m, _fm, "") #define UART2Init Uart2Init #define UART2CheckFreeSpace Uart2CheckFreeSpace @@ -99,18 +131,20 @@ extern bool_t uart2_check_free_space( uint8_t len); #define UART2ChAvailable Uart2ChAvailable #define UART2Getch Uart2Getch -#endif /* USE_UART2 */ +#endif // USE_UART2 #ifdef USE_UART3 +extern struct uart_periph uart3; +extern void uart3_init(void); -extern void uart3_init( void ); -extern void uart3_transmit( uint8_t data ); -extern bool_t uart3_check_free_space( uint8_t len); - -#define Uart3Init uart3_init -#define Uart3CheckFreeSpace(_x) uart3_check_free_space(_x) -#define Uart3Transmit(_x) uart3_transmit(_x) +#define Uart3Init() uart_periph_init(&uart3) +#define Uart3CheckFreeSpace(_x) uart_check_free_space(&uart3, _x) +#define Uart3Transmit(_x) uart_transmit(&uart3, _x) #define Uart3SendMessage() {} +#define Uart3ChAvailable() UartChAvailable(uart3) +#define Uart3Getch() UartGetch(uart3) +#define Uart3TxRunning uart3.tx_running +#define Uart3InitParam(_b, _m, _fm) uart_periph_init_param(&uart3, _b, _m, _fm, "") #define UART3Init Uart3Init #define UART3CheckFreeSpace Uart3CheckFreeSpace @@ -119,6 +153,6 @@ extern bool_t uart3_check_free_space( uint8_t len); #define UART3ChAvailable Uart3ChAvailable #define UART3Getch Uart3Getch -#endif /* USE_UART3 */ +#endif // USE_UART3 -#endif /* MCU_PERIPH_UART_H */ +#endif /* UART_H */