diff --git a/sw/airborne/arch/lpc21/mcu_periph/uart_arch.c b/sw/airborne/arch/lpc21/mcu_periph/uart_arch.c index 4e98eb8123..8d94426849 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 ff5f49445e..ebbce01fa4 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) { diff --git a/sw/airborne/arch/stm32/mcu_periph/uart_arch.c b/sw/airborne/arch/stm32/mcu_periph/uart_arch.c index 130601e581..75eddfd531 100644 --- a/sw/airborne/arch/stm32/mcu_periph/uart_arch.c +++ b/sw/airborne/arch/stm32/mcu_periph/uart_arch.c @@ -29,15 +29,22 @@ #include #include "std.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_set_baudrate((u32)p->reg_addr, baud); usart_set_databits((u32)p->reg_addr, 8); usart_set_stopbits((u32)p->reg_addr, USART_STOPBITS_1); usart_set_parity((u32)p->reg_addr, USART_PARITY_NONE); - usart_set_flow_control((u32)p->reg_addr, USART_FLOWCONTROL_NONE); usart_set_mode((u32)p->reg_addr, USART_MODE_TX_RX); + + if (hw_flow_control) { + usart_set_flow_control((u32)p->reg_addr, USART_FLOWCONTROL_RTS_CTS); + } + else { + usart_set_flow_control((u32)p->reg_addr, USART_FLOWCONTROL_NONE); + } + /* Enable USART1 Receive interrupts */ USART_CR1((u32)p->reg_addr) |= USART_CR1_RXNEIE; @@ -126,8 +133,19 @@ void uart1_init( void ) { gpio_set_mode(GPIO_BANK_USART1_RX, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO_USART1_RX); - /* Configure USART */ - uart_periph_set_baudrate(&uart1, UART1_BAUD); +#if UART1_HW_FLOW_CONTROL +#warning "USING UART1 FLOW CONTROL. Make sure to pull down CTS if you are not connecting any flow-control-capable hardware." + gpio_set_mode(GPIO_BANK_USART1_RTS, GPIO_MODE_OUTPUT_50_MHZ, + GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART1_RTS); + gpio_set_mode(GPIO_BANK_USART1_CTS, GPIO_MODE_INPUT, + GPIO_CNF_INPUT_FLOAT, GPIO_USART1_CTS); + + /* 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_isr(void) { usart_isr(&uart1); } @@ -155,7 +173,7 @@ void uart2_init( void ) { GPIO_CNF_INPUT_FLOAT, GPIO_USART2_RX); /* Configure USART */ - uart_periph_set_baudrate(&uart2, UART2_BAUD); + uart_periph_set_baudrate(&uart2, UART2_BAUD, FALSE); } void usart2_isr(void) { usart_isr(&uart2); } @@ -185,7 +203,7 @@ void uart3_init( void ) { GPIO_CNF_INPUT_FLOAT, GPIO_USART3_PR_RX); /* Configure USART */ - uart_periph_set_baudrate(&uart3, UART3_BAUD); + uart_periph_set_baudrate(&uart3, UART3_BAUD, FALSE); } void usart3_isr(void) { usart_isr(&uart3); } @@ -214,7 +232,7 @@ void uart5_init( void ) { GPIO_CNF_INPUT_FLOAT, GPIO_UART5_RX); /* Configure USART */ - uart_periph_set_baudrate(&uart5, UART5_BAUD); + uart_periph_set_baudrate(&uart5, UART5_BAUD, FALSE); } void uart5_isr(void) { usart_isr(&uart5); } diff --git a/sw/airborne/mcu_periph/uart.h b/sw/airborne/mcu_periph/uart.h index 1a4f487cbc..a8107ab99e 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, FALSE) //#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 f99f70f5a7..f16ddf08c9 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 a2c639d531..d6b9a66cb9 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 6e11af4988..a7e0e87233 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 375559631d..9173d4b5df 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 d910eda6eb..86d7d871c0 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); + "-shfc", 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