From 276a8e5f14de7615f92bc9514525d898704df5f2 Mon Sep 17 00:00:00 2001 From: Dirk Dokter Date: Tue, 11 Sep 2012 18:45:29 +0200 Subject: [PATCH 1/2] [stm32][ground_segment] Add UART hardware flow control * ground segment: serial ocaml lib, link and logalizer * Added UART hardware flow control to UART1 for STM32 --- sw/airborne/arch/stm32/mcu_periph/uart_arch.c | 37 +++++++++++++++---- sw/airborne/arch/stm32/mcu_periph/uart_arch.h | 8 ++++ sw/airborne/mcu_periph/uart.h | 16 +++++--- sw/ground_segment/tmtc/link.ml | 4 +- sw/lib/ocaml/cserial.c | 12 ++++-- sw/lib/ocaml/serial.ml | 6 +-- sw/lib/ocaml/serial.mli | 2 +- sw/logalizer/play_core.ml | 6 ++- 8 files changed, 67 insertions(+), 24 deletions(-) diff --git a/sw/airborne/arch/stm32/mcu_periph/uart_arch.c b/sw/airborne/arch/stm32/mcu_periph/uart_arch.c index 76b4c6dc207..b2107577c72 100644 --- a/sw/airborne/arch/stm32/mcu_periph/uart_arch.c +++ b/sw/airborne/arch/stm32/mcu_periph/uart_arch.c @@ -30,7 +30,7 @@ #include "std.h" #include "pprz_baudrate.h" -void uart_periph_set_baudrate(struct uart_periph* p, uint32_t baud) { +void uart_periph_set_baudrate(struct uart_periph* p, uint32_t baud, bool_t hw_flow_control) { /* Configure USART */ USART_InitTypeDef usart; @@ -38,7 +38,12 @@ void uart_periph_set_baudrate(struct uart_periph* p, uint32_t baud) { usart.USART_WordLength = USART_WordLength_8b; usart.USART_StopBits = USART_StopBits_1; usart.USART_Parity = USART_Parity_No; - usart.USART_HardwareFlowControl = USART_HardwareFlowControl_None; + if (hw_flow_control) { + usart.USART_HardwareFlowControl = USART_HardwareFlowControl_RTS_CTS; + } + else { + usart.USART_HardwareFlowControl = USART_HardwareFlowControl_None; + } usart.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(p->reg_addr, &usart); /* Enable USART1 Receive interrupts */ @@ -136,8 +141,25 @@ void uart1_init( void ) { gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(UART1_RxPort, &gpio); - /* Configure USART1 */ - uart_periph_set_baudrate(&uart1, UART1_BAUD); +#if UART1_HW_FLOW_CONTROL +#warning "USING UART1 HW FLOW CONTROL. Make sure to pull down CTS if you are not connecting any flow-control-capable hardware." + /* GPIOA: GPIO_Pin_12 USART1 Rts push-pull */ + gpio.GPIO_Pin = UART1_RtsPin; + gpio.GPIO_Mode = GPIO_Mode_AF_PP; + gpio.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(UART1_FlowControlPort, &gpio); + + /* GPIOA: GPIO_Pin_11 USART1 Cts pin as floating input */ + gpio.GPIO_Pin = UART1_CtsPin; + gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_Init(UART1_FlowControlPort, &gpio); + + /* Configure USART1, enable hardware flow control*/ + uart_periph_set_baudrate(&uart1, UART1_BAUD, TRUE); +#else + /* Configure USART1, no flow control */ + uart_periph_set_baudrate(&uart1, UART1_BAUD, FALSE); +#endif } void usart1_irq_handler(void) { usart_irq_handler(&uart1); } @@ -171,7 +193,7 @@ void uart2_init( void ) { GPIO_Init(UART2_RxPort, &gpio); /* Configure USART2 */ - uart_periph_set_baudrate(&uart2, UART2_BAUD); + uart_periph_set_baudrate(&uart2, UART2_BAUD, FALSE); } void usart2_irq_handler(void) { usart_irq_handler(&uart2); } @@ -207,7 +229,7 @@ void uart3_init( void ) { GPIO_Init(UART3_RxPort, &gpio); /* Configure USART3 */ - uart_periph_set_baudrate(&uart3, UART3_BAUD); + uart_periph_set_baudrate(&uart3, UART3_BAUD, FALSE); } void usart3_irq_handler(void) { usart_irq_handler(&uart3); } @@ -242,10 +264,9 @@ void uart5_init( void ) { GPIO_Init(UART5_RxPort, &gpio); /* Configure UART5 */ - uart_periph_set_baudrate(&uart5, UART5_BAUD); + uart_periph_set_baudrate(&uart5, UART5_BAUD, FALSE); } void usart5_irq_handler(void) { usart_irq_handler(&uart5); } #endif /* USE_UART5 */ - diff --git a/sw/airborne/arch/stm32/mcu_periph/uart_arch.h b/sw/airborne/arch/stm32/mcu_periph/uart_arch.h index 45ff4afc4c4..dbd6ae75236 100644 --- a/sw/airborne/arch/stm32/mcu_periph/uart_arch.h +++ b/sw/airborne/arch/stm32/mcu_periph/uart_arch.h @@ -55,6 +55,9 @@ #define UART3_RxPin GPIO_Pin_11 #define UART5_RxPin GPIO_Pin_2 +#define UART1_CtsPin GPIO_Pin_11 +#define UART1_RtsPin GPIO_Pin_12 + #define UART1_TxPort GPIOA #define UART2_TxPort GPIOA #define UART3_TxPort GPIOC @@ -65,6 +68,8 @@ #define UART3_RxPort GPIOC #define UART5_RxPort GPIOD +#define UART1_FlowControlPort GPIOA + #define UART1_Periph RCC_APB2Periph_GPIOA #define UART2_Periph RCC_APB2Periph_GPIOA #define UART3_Periph RCC_APB2Periph_GPIOC @@ -112,6 +117,9 @@ #define UART3_reg USART3 #define UART5_reg USART5 +#if defined UART1_FLOW_CONTROL +#error UART1_FLOW_CONTROL is renamed to UART1_HW_FLOW_CONTROL +#endif #if defined USE_UART1 || OVERRIDE_UART1_IRQ_HANDLER extern void usart1_irq_handler(void); diff --git a/sw/airborne/mcu_periph/uart.h b/sw/airborne/mcu_periph/uart.h index 1a4f487cbcb..dd49fab2aef 100644 --- a/sw/airborne/mcu_periph/uart.h +++ b/sw/airborne/mcu_periph/uart.h @@ -57,7 +57,7 @@ struct uart_periph { }; extern void uart_periph_init(struct uart_periph* p); -extern void uart_periph_set_baudrate(struct uart_periph* p, uint32_t baud); +extern void uart_periph_set_baudrate(struct uart_periph* p, uint32_t baud, bool_t hw_flow_control); //extern void uart_periph_init_param(struct uart_periph* p, uint32_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); @@ -82,7 +82,7 @@ extern void uart0_init(void); #define Uart0ChAvailable() UartChAvailable(uart0) #define Uart0Getch() UartGetch(uart0) #define Uart0TxRunning uart0.tx_running -#define Uart0SetBaudrate(_b) uart_periph_set_baudrate(&uart0, _b) +#define Uart0SetBaudrate(_b) uart_periph_set_baudrate(&uart0, _b, 0) //#define Uart0InitParam(_b, _m, _fm) uart_periph_init_param(&uart0, _b, _m, _fm, "") #define UART0Init Uart0Init @@ -107,7 +107,11 @@ extern void uart1_init(void); #define Uart1ChAvailable() UartChAvailable(uart1) #define Uart1Getch() UartGetch(uart1) #define Uart1TxRunning uart1.tx_running -#define Uart1SetBaudrate(_b) uart_periph_set_baudrate(&uart1, _b) +#if UART1_HW_FLOW_CONTROL +#define Uart1SetBaudrate(_b) uart_periph_set_baudrate(&uart1, _b, TRUE) +#else +#define Uart1SetBaudrate(_b) uart_periph_set_baudrate(&uart1, _b, FALSE) +#endif //#define Uart1InitParam(_b, _m, _fm) uart_periph_init_param(&uart1, _b, _m, _fm, "") #define UART1Init Uart1Init @@ -132,7 +136,7 @@ extern void uart2_init(void); #define Uart2ChAvailable() UartChAvailable(uart2) #define Uart2Getch() UartGetch(uart2) #define Uart2TxRunning uart2.tx_running -#define Uart2SetBaudrate(_b) uart_periph_set_baudrate(&uart2, _b) +#define Uart2SetBaudrate(_b) uart_periph_set_baudrate(&uart2, _b, FALSE) //#define Uart2InitParam(_b, _m, _fm) uart_periph_init_param(&uart2, _b, _m, _fm, "") #define UART2Init Uart2Init @@ -157,7 +161,7 @@ extern void uart3_init(void); #define Uart3ChAvailable() UartChAvailable(uart3) #define Uart3Getch() UartGetch(uart3) #define Uart3TxRunning uart3.tx_running -#define Uart3SetBaudrate(_b) uart_periph_set_baudrate(&uart3, _b) +#define Uart3SetBaudrate(_b) uart_periph_set_baudrate(&uart3, _b, FALSE) //#define Uart3InitParam(_b, _m, _fm) uart_periph_init_param(&uart3, _b, _m, _fm, "") #define UART3Init Uart3Init @@ -182,7 +186,7 @@ extern void uart5_init(void); #define Uart5ChAvailable() UartChAvailable(uart5) #define Uart5Getch() UartGetch(uart5) #define Uart5TxRunning uart5.tx_running -#define Uart5SetBaudrate(_b) uart_periph_set_baudrate(&uart5, _b) +#define Uart5SetBaudrate(_b) uart_periph_set_baudrate(&uart5, _b, FALSE) //#define Uart5InitParam(_b, _m, _fm) uart_periph_init_param(&uart5, _b, _m, _fm, "") #define UART5Init Uart5Init diff --git a/sw/ground_segment/tmtc/link.ml b/sw/ground_segment/tmtc/link.ml index f99f70f5a71..f16ddf08c9e 100644 --- a/sw/ground_segment/tmtc/link.ml +++ b/sw/ground_segment/tmtc/link.ml @@ -426,6 +426,7 @@ let () = let ivy_bus = ref Defivybus.default_ivy_bus and port = ref "/dev/ttyUSB0" and baudrate = ref "9600" + and hw_flow_control = ref false and transport = ref "pprz" and uplink = ref true and audio = ref false @@ -443,6 +444,7 @@ let () = "-noac_info", Arg.Clear ac_info, (sprintf "Disables AC traffic info (uplink)."); "-nouplink", Arg.Clear uplink, (sprintf "Disables the uplink (from the ground to the aircraft)."); "-s", Arg.Set_string baudrate, (sprintf " Default is %s" !baudrate); + "-hfc", Arg.Set hw_flow_control, "Enable UART hardware flow control (CTS/RTS)"; "-local_timestamp", Arg.Unit (fun () -> add_timestamp := Some (Unix.gettimeofday ())), "Add local timestamp to messages sent over ivy"; "-transport", Arg.Set_string transport, (sprintf " Available protocols are modem,pprz,pprz2 and xbee. Default is %s" !transport); "-udp", Arg.Set udp, "Listen a UDP connection on "; @@ -475,7 +477,7 @@ let () = end else if !audio then Demod.init !port else if on_serial_device then - Serial.opendev !port (Serial.speed_of_baudrate !baudrate) + Serial.opendev !port (Serial.speed_of_baudrate !baudrate) !hw_flow_control else Unix.openfile !port [Unix.O_RDWR] 0o640 in diff --git a/sw/lib/ocaml/cserial.c b/sw/lib/ocaml/cserial.c index 878a3b4b445..759dba06551 100644 --- a/sw/lib/ocaml/cserial.c +++ b/sw/lib/ocaml/cserial.c @@ -40,7 +40,7 @@ static int baudrates[] = { B0, B50, B75, B110, B134, B150, B200, B300, B600, B12 /****************************************************************************/ /* Open serial device for requested protocoll */ /****************************************************************************/ -value c_init_serial(value device, value speed) +value c_init_serial(value device, value speed, value hw_flow_control) { struct termios orig_termios, cur_termios; @@ -63,8 +63,14 @@ value c_init_serial(value device, value speed) cur_termios.c_oflag &=~(OPOST|ONLCR|OCRNL|ONOCR|ONLRET); /* control modes */ - cur_termios.c_cflag &= ~(CSIZE|CSTOPB|CREAD|PARENB|PARODD|HUPCL|CLOCAL|CRTSCTS); - cur_termios.c_cflag |= CREAD|CS8|CLOCAL; + if (Bool_val(hw_flow_control)) { + cur_termios.c_cflag &= ~(CSIZE|CSTOPB|CREAD|PARENB|PARODD|HUPCL|CLOCAL); + cur_termios.c_cflag |= CREAD|CS8|CLOCAL|CRTSCTS; + } + else { + cur_termios.c_cflag &= ~(CSIZE|CSTOPB|CREAD|PARENB|PARODD|HUPCL|CLOCAL|CRTSCTS); + cur_termios.c_cflag |= CREAD|CS8|CLOCAL; + } /* local modes */ cur_termios.c_lflag &= ~(ISIG|ICANON|IEXTEN|ECHO|FLUSHO|PENDIN); diff --git a/sw/lib/ocaml/serial.ml b/sw/lib/ocaml/serial.ml index 6e11af49887..a7e0e872335 100644 --- a/sw/lib/ocaml/serial.ml +++ b/sw/lib/ocaml/serial.ml @@ -77,13 +77,13 @@ let string_of_payload = fun x -> x let payload_of_string = fun x -> x -external init_serial : string -> speed -> Unix.file_descr = "c_init_serial" +external init_serial : string -> speed -> bool -> Unix.file_descr = "c_init_serial" external set_dtr : Unix.file_descr -> bool -> unit = "c_set_dtr" external set_speed : Unix.file_descr -> speed -> unit = "c_serial_set_baudrate" -let opendev device speed = +let opendev device speed hw_flow_control = try - init_serial device speed + init_serial device speed hw_flow_control with Failure x -> failwith (Printf.sprintf "Error %s (%s)" x device) diff --git a/sw/lib/ocaml/serial.mli b/sw/lib/ocaml/serial.mli index 375559631d4..9173d4b5df5 100644 --- a/sw/lib/ocaml/serial.mli +++ b/sw/lib/ocaml/serial.mli @@ -49,7 +49,7 @@ type speed = val speed_of_baudrate : string -> speed -val opendev : string -> speed -> Unix.file_descr +val opendev : string -> speed -> bool -> Unix.file_descr val close : Unix.file_descr -> unit val set_dtr : Unix.file_descr -> bool -> unit val set_speed : Unix.file_descr -> speed -> unit diff --git a/sw/logalizer/play_core.ml b/sw/logalizer/play_core.ml index d910eda6eb9..252fbd0c10d 100644 --- a/sw/logalizer/play_core.ml +++ b/sw/logalizer/play_core.ml @@ -122,6 +122,7 @@ let was_running = ref false let bus = ref Defivybus.default_ivy_bus let port = ref "/dev/ttyUSB0" let baudrate = ref "9600" +let hw_flow_control = ref false let file_to_load = ref "" let output_on_serial = ref false @@ -177,7 +178,8 @@ let init = fun () -> [ "-b", Arg.String (fun x -> bus := x), (sprintf " Default is %s" !bus); "-d", Arg.Set_string port, (sprintf " Default is %s" !port); "-o", Arg.Set output_on_serial, "Output binary messages on serial port"; - "-s", Arg.Set_string baudrate, (sprintf " Default is %s" !baudrate)] + "-s", Arg.Set_string baudrate, (sprintf " Default is %s" !baudrate); + "-hfc", Arg.Set hw_flow_control, "Enable UART hardware flow control (CTS/RTS)";] (fun x -> file_to_load := x) "Usage: "; @@ -187,7 +189,7 @@ let init = fun () -> let serial_port = if !output_on_serial then - Some (Unix.out_channel_of_descr (Serial.opendev !port (Serial.speed_of_baudrate !baudrate))) + Some (Unix.out_channel_of_descr (Serial.opendev !port (Serial.speed_of_baudrate !baudrate) !hw_flow_control)) else None in From 91ef1c9e17ce0d7760c24522a3b6dc2a3a3fba18 Mon Sep 17 00:00:00 2001 From: Felix Ruess Date: Fri, 5 Oct 2012 17:28:42 +0200 Subject: [PATCH 2/2] [arch] add hw_flow_control flag to uart_periph_set_baudrate for lpc21 and omap (unused there though) --- sw/airborne/arch/lpc21/mcu_periph/uart_arch.c | 2 +- sw/airborne/arch/omap/mcu_periph/uart_arch.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sw/airborne/arch/lpc21/mcu_periph/uart_arch.c b/sw/airborne/arch/lpc21/mcu_periph/uart_arch.c index 4e98eb81234..8d944268499 100644 --- a/sw/airborne/arch/lpc21/mcu_periph/uart_arch.c +++ b/sw/airborne/arch/lpc21/mcu_periph/uart_arch.c @@ -56,7 +56,7 @@ static inline void uart_set_baudrate(struct uart_periph* p, uint32_t baud) { ((uartRegs_t *)(p->reg_addr))->fcr = UART_FIFO_8; } -void uart_periph_set_baudrate(struct uart_periph* p, uint32_t baud) { +void uart_periph_set_baudrate(struct uart_periph* p, uint32_t baud, bool_t hw_flow_control __attribute__ ((unused))) { uart_disable_interrupts(p); uart_set_baudrate(p, baud); uart_enable_interrupts(p); diff --git a/sw/airborne/arch/omap/mcu_periph/uart_arch.c b/sw/airborne/arch/omap/mcu_periph/uart_arch.c index ff5f49445e7..ebbce01fa43 100644 --- a/sw/airborne/arch/omap/mcu_periph/uart_arch.c +++ b/sw/airborne/arch/omap/mcu_periph/uart_arch.c @@ -32,7 +32,7 @@ #include "fms/fms_serial_port.h" -void uart_periph_set_baudrate(struct uart_periph* p, uint16_t baud) { +void uart_periph_set_baudrate(struct uart_periph* p, uint16_t baud, bool_t hw_flow_control __attribute__ ((unused))) { struct FmsSerialPort* fmssp; // close serial port if already open if (p->reg_addr != NULL) {