From f91f212d9fef66e515935a52712613550a04ca65 Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Mon, 7 Sep 2015 09:23:46 +0200 Subject: [PATCH] cc3200: New UART API plus related test. --- cc3200/boards/LAUNCHXL/mpconfigboard.h | 7 +- cc3200/misc/mpcallback.c | 8 + cc3200/misc/mpcallback.h | 1 + cc3200/mods/pybpin.c | 59 ++-- cc3200/mods/pybpin.h | 5 + cc3200/mods/pybtimer.c | 20 -- cc3200/mods/pybtimer.h | 1 - cc3200/mods/pybuart.c | 366 ++++++++++--------------- cc3200/mods/pybuart.h | 11 +- cc3200/mpconfigport.h | 1 + cc3200/mptask.c | 16 +- cc3200/qstrdefsport.h | 22 +- docs/library/pyb.UART.rst | 75 +++-- tests/wipy/pin.py | 3 +- tests/wipy/uart.py | 87 ++++++ tests/wipy/uart.py.exp | 28 ++ 16 files changed, 374 insertions(+), 336 deletions(-) create mode 100644 tests/wipy/uart.py create mode 100644 tests/wipy/uart.py.exp diff --git a/cc3200/boards/LAUNCHXL/mpconfigboard.h b/cc3200/boards/LAUNCHXL/mpconfigboard.h index 028cd9dee7..d0ece9b8db 100644 --- a/cc3200/boards/LAUNCHXL/mpconfigboard.h +++ b/cc3200/boards/LAUNCHXL/mpconfigboard.h @@ -35,13 +35,8 @@ #define MICROPY_HW_ENABLE_RTC (1) #define MICROPY_HW_ANTENNA_DIVERSITY (0) -#define MICROPY_STDIO_UART 1 +#define MICROPY_STDIO_UART 0 #define MICROPY_STDIO_UART_BAUD 115200 -#define MICROPY_STDIO_UART_RX_BUF_SIZE 128 -#define MICROPY_STDIO_UART_TX_PIN (pin_GP1) -#define MICROPY_STDIO_UART_RX_PIN (pin_GP2) -#define MICROPY_STDIO_UART_TX_PIN_AF PIN_MODE_3 -#define MICROPY_STDIO_UART_RX_PIN_AF PIN_MODE_3 #define MICROPY_SYS_LED_PRCM PRCM_GPIOA1 #define MICROPY_SAFE_BOOT_PRCM PRCM_GPIOA2 diff --git a/cc3200/misc/mpcallback.c b/cc3200/misc/mpcallback.c index 2dfd5e006a..8e7a9f740a 100644 --- a/cc3200/misc/mpcallback.c +++ b/cc3200/misc/mpcallback.c @@ -91,6 +91,14 @@ void mpcallback_wake_all (void) { } } +void mpcallback_disable_all (void) { + // re-enable all active callback objects one by one + for (mp_uint_t i = 0; i < MP_STATE_PORT(mpcallback_obj_list).len; i++) { + mpcallback_obj_t *callback_obj = ((mpcallback_obj_t *)(MP_STATE_PORT(mpcallback_obj_list).items[i])); + callback_obj->methods->disable(callback_obj->parent); + } +} + void mpcallback_remove (const mp_obj_t parent) { mpcallback_obj_t *callback_obj; if ((callback_obj = mpcallback_find(parent))) { diff --git a/cc3200/misc/mpcallback.h b/cc3200/misc/mpcallback.h index 6492a2e99e..cc15a3ac65 100644 --- a/cc3200/misc/mpcallback.h +++ b/cc3200/misc/mpcallback.h @@ -65,6 +65,7 @@ void mpcallback_init0 (void); mp_obj_t mpcallback_new (mp_obj_t parent, mp_obj_t handler, const mp_cb_methods_t *methods, bool enable); mpcallback_obj_t *mpcallback_find (mp_obj_t parent); void mpcallback_wake_all (void); +void mpcallback_disable_all (void); void mpcallback_remove (const mp_obj_t parent); void mpcallback_handler (mp_obj_t self_in); uint mpcallback_translate_priority (uint priority); diff --git a/cc3200/mods/pybpin.c b/cc3200/mods/pybpin.c index 01fd522927..cae2f68942 100644 --- a/cc3200/mods/pybpin.c +++ b/cc3200/mods/pybpin.c @@ -110,9 +110,8 @@ STATIC pybpin_wake_pin_t pybpin_wake_pin[PYBPIN_NUM_WAKE_PINS] = void pin_init0(void) { // this initalization also reconfigures the JTAG/SWD pins #ifndef DEBUG - // GP10 and GP11 must be assigned to the GPIO peripheral (the default is I2C), so that the I2C bus - // can then be assigned safely to any other pins (as recomended by the SDK release notes). - // Anyway, we initialize all pins here, as inputs WITHOUT any pull resistor enabled + // assign all pins to the GPIO module so that peripherals can be connected to any + // pins without conflicts after a soft reset mp_map_t *named_map = mp_obj_dict_get_map((mp_obj_t)&pin_board_pins_locals_dict); for (uint i = 0; i < named_map->used - 1; i++) { pin_obj_t * pin = (pin_obj_t *)named_map->table[i].value; @@ -555,20 +554,6 @@ STATIC mp_obj_t pin_value(mp_uint_t n_args, const mp_obj_t *args) { } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_value_obj, 1, 2, pin_value); -STATIC mp_obj_t pin_low(mp_obj_t self_in) { - pin_obj_t *self = self_in; - MAP_GPIOPinWrite(self->port, self->bit, 0); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_low_obj, pin_low); - -STATIC mp_obj_t pin_high(mp_obj_t self_in) { - pin_obj_t *self = self_in; - MAP_GPIOPinWrite(self->port, self->bit, self->bit); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_high_obj, pin_high); - STATIC mp_obj_t pin_toggle(mp_obj_t self_in) { pin_obj_t *self = self_in; MAP_GPIOPinWrite(self->port, self->bit, ~MAP_GPIOPinRead(self->port, self->bit)); @@ -624,6 +609,26 @@ STATIC mp_obj_t pin_drive(mp_uint_t n_args, const mp_obj_t *args) { } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_drive_obj, 1, 2, pin_drive); +STATIC mp_obj_t pin_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 0, 1, false); + mp_obj_t _args[2] = {self_in, *args}; + return pin_value (n_args + 1, _args); +} + +STATIC mp_obj_t pin_alt_list(mp_obj_t self_in) { + pin_obj_t *self = self_in; + mp_obj_t af[2]; + mp_obj_t afs = mp_obj_new_list(0, NULL); + + for (int i = 0; i < self->num_afs; i++) { + af[0] = MP_OBJ_NEW_QSTR(self->af_list[i].name); + af[1] = mp_obj_new_int(self->af_list[i].idx); + mp_obj_list_append(afs, mp_obj_new_tuple(MP_ARRAY_SIZE(af), af)); + } + return afs; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_alt_list_obj, pin_alt_list); + STATIC mp_obj_t pin_callback (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { mp_arg_val_t args[mpcallback_INIT_NUM_ARGS]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, mpcallback_INIT_NUM_ARGS, mpcallback_init_args, args); @@ -755,26 +760,6 @@ invalid_args: } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pin_callback_obj, 1, pin_callback); -STATIC mp_obj_t pin_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { - mp_arg_check_num(n_args, n_kw, 0, 1, false); - mp_obj_t _args[2] = {self_in, *args}; - return pin_value (n_args + 1, _args); -} - -STATIC mp_obj_t pin_alt_list(mp_obj_t self_in) { - pin_obj_t *self = self_in; - mp_obj_t af[2]; - mp_obj_t afs = mp_obj_new_list(0, NULL); - - for (int i = 0; i < self->num_afs; i++) { - af[0] = MP_OBJ_NEW_QSTR(self->af_list[i].name); - af[1] = mp_obj_new_int(self->af_list[i].idx); - mp_obj_list_append(afs, mp_obj_new_tuple(MP_ARRAY_SIZE(af), af)); - } - return afs; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_alt_list_obj, pin_alt_list); - STATIC const mp_map_elem_t pin_locals_dict_table[] = { // instance methods { MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pin_init_obj }, diff --git a/cc3200/mods/pybpin.h b/cc3200/mods/pybpin.h index 04b80825dd..4c49e63ab5 100644 --- a/cc3200/mods/pybpin.h +++ b/cc3200/mods/pybpin.h @@ -115,6 +115,11 @@ typedef struct { uint8_t used : 1; } pin_obj_t; +typedef struct { + pin_obj_t *pin; + uint8_t af_idx; +} pin_fn_t; + extern const mp_obj_type_t pin_type; typedef struct { diff --git a/cc3200/mods/pybtimer.c b/cc3200/mods/pybtimer.c index 69e1c827c9..bd3a935654 100644 --- a/cc3200/mods/pybtimer.c +++ b/cc3200/mods/pybtimer.c @@ -142,26 +142,6 @@ void timer_init0 (void) { mp_obj_list_init(&MP_STATE_PORT(pyb_timer_channel_obj_list), 0); } -void timer_disable_all (void) { - pyb_timer_obj_t timer = { - .timer = TIMERA0_BASE, - .intflags = TIMER_CAPB_EVENT | TIMER_CAPB_MATCH | - TIMER_TIMB_TIMEOUT | TIMER_CAPA_EVENT | - TIMER_CAPA_MATCH | TIMER_TIMA_TIMEOUT, - .peripheral = PRCM_TIMERA0 - }; - - for (uint32_t i = 0; i < PYBTIMER_NUM_TIMERS; i++) { - // in case it's not clocked - MAP_PRCMPeripheralClkEnable(timer.peripheral, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK); - timer_disable(&timer); - // timer base offset according to hw_memmap.h - timer.timer += 0x1000; - // peripheral offset according to prcm.h - timer.peripheral++; - } -} - void pyb_timer_channel_callback_enable (mp_obj_t self_in) { pyb_timer_channel_obj_t *self = self_in; MAP_TimerIntClear(self->timer->timer, self->timer->intflags & self->channel); diff --git a/cc3200/mods/pybtimer.h b/cc3200/mods/pybtimer.h index 849e41ed74..4e9de138d8 100644 --- a/cc3200/mods/pybtimer.h +++ b/cc3200/mods/pybtimer.h @@ -34,5 +34,4 @@ extern const mp_obj_type_t pyb_timer_type; DECLARE PUBLIC FUNCTIONS ******************************************************************************/ void timer_init0 (void); -void timer_disable_all (void); diff --git a/cc3200/mods/pybuart.c b/cc3200/mods/pybuart.c index 4af9de61d7..cb010395bd 100644 --- a/cc3200/mods/pybuart.c +++ b/cc3200/mods/pybuart.c @@ -52,51 +52,30 @@ #include "py/mpstate.h" #include "osi.h" #include "utils.h" +#include "pin.h" +#include "pybpin.h" +#include "pins.h" /// \moduleref pyb /// \class UART - duplex serial communication bus -/// -/// UART implements the standard UART/USART duplex serial communications protocol. At -/// the physical level it consists of 2 lines: RX and TX. -/// -/// UART objects can be created and initialised using: -/// -/// from pyb import UART -/// -/// uart = UART(1, 9600) # init with given baudrate -/// uart.init(9600, bits=8, stop=1, parity=None) # init with given parameters -/// -/// Bits can be 5, 6, 7, 8, parity can be None, 0 (even), 1 (odd). Stop can be 1 or 2. -/// -/// A UART object acts like a stream object and reading and writing is done -/// using the standard stream methods: -/// -/// uart.read(10) # read 10 characters, returns a bytes object -/// uart.readall() # read all available characters -/// uart.readline() # read a line -/// uart.readinto(buf) # read and store into the given buffer -/// uart.write('abc') # write the 3 characters -/// -/// Individual characters can be read/written using: -/// -/// uart.readchar() # read 1 character and returns it as an integer -/// uart.writechar(42) # write 1 character -/// -/// To check if there is anything to be read, use: -/// -/// uart.any() # returns True if any characters waiting /****************************************************************************** DEFINE CONSTANTS - ******************************************************************************/ -#define PYBUART_TX_WAIT_US (50) + *******-***********************************************************************/ +#define PYBUART_FRAME_TIME_US(baud) ((11 * 1000000) / baud) +#define PYBUART_2_FRAMES_TIME_US(baud) (PYBUART_FRAME_TIME_US(baud) * 2) +#define PYBUART_RX_TIMEOUT_US(baud) (PYBUART_2_FRAMES_TIME_US(baud)) + +#define PYBUART_TX_WAIT_US(baud) ((PYBUART_FRAME_TIME_US(baud)) + 1) #define PYBUART_TX_MAX_TIMEOUT_MS (5) +#define PYBUART_RX_BUFFER_LEN (128) + /****************************************************************************** DECLARE PRIVATE FUNCTIONS ******************************************************************************/ STATIC void uart_init (pyb_uart_obj_t *self); -STATIC bool uart_rx_wait (pyb_uart_obj_t *self, uint32_t timeout); +STATIC bool uart_rx_wait (pyb_uart_obj_t *self); STATIC void UARTGenericIntHandler(uint32_t uart_id); STATIC void UART0IntHandler(void); STATIC void UART1IntHandler(void); @@ -115,36 +94,45 @@ struct _pyb_uart_obj_t { uint config; uint flowcontrol; byte *read_buf; // read buffer pointer - uint16_t timeout; // timeout waiting for first char - uint16_t timeout_char; // timeout waiting between chars - uint16_t read_buf_len; // len in chars; buf can hold len-1 chars volatile uint16_t read_buf_head; // indexes first empty slot uint16_t read_buf_tail; // indexes first full slot (not full if equals head) byte peripheral; + byte irq_trigger; }; /****************************************************************************** DECLARE PRIVATE DATA ******************************************************************************/ -STATIC pyb_uart_obj_t pyb_uart_obj[PYB_NUM_UARTS] = {{.reg = UARTA0_BASE, .baudrate = 0, .peripheral = PRCM_UARTA0}, - {.reg = UARTA1_BASE, .baudrate = 0, .peripheral = PRCM_UARTA1}}; +STATIC pyb_uart_obj_t pyb_uart_obj[PYB_NUM_UARTS] = { {.reg = UARTA0_BASE, .baudrate = 0, .read_buf = NULL, .peripheral = PRCM_UARTA0}, + {.reg = UARTA1_BASE, .baudrate = 0, .read_buf = NULL, .peripheral = PRCM_UARTA1} }; STATIC const mp_cb_methods_t uart_cb_methods; +STATIC const pin_fn_t pyb_uart_def_pin[PYB_NUM_UARTS][2] = { {{.pin = &pin_GP1, .af_idx = 3}, {.pin = &pin_GP2, .af_idx = 3}}, + {{.pin = &pin_GP3, .af_idx = 6}, {.pin = &pin_GP4, .af_idx = 6}} }; + /****************************************************************************** DEFINE PUBLIC FUNCTIONS ******************************************************************************/ void uart_init0 (void) { + // save references of the UART objects, to prevent the read buffers from being trashed by the gc + MP_STATE_PORT(pyb_uart_objs)[0] = &pyb_uart_obj[0]; + MP_STATE_PORT(pyb_uart_objs)[1] = &pyb_uart_obj[1]; } -bool uart_rx_any(pyb_uart_obj_t *self) { - return (self->read_buf_tail != self->read_buf_head || MAP_UARTCharsAvail(self->reg)); +uint32_t uart_rx_any(pyb_uart_obj_t *self) { + if (self->read_buf_tail != self->read_buf_head) { + // buffering via irq + return (self->read_buf_head > self->read_buf_tail) ? self->read_buf_head - self->read_buf_tail : + PYBUART_RX_BUFFER_LEN - self->read_buf_tail + self->read_buf_head; + } + return MAP_UARTCharsAvail(self->reg) ? 1 : 0; } int uart_rx_char(pyb_uart_obj_t *self) { if (self->read_buf_tail != self->read_buf_head) { - // buffering via IRQ + // buffering via irq int data = self->read_buf[self->read_buf_tail]; - self->read_buf_tail = (self->read_buf_tail + 1) % self->read_buf_len; + self->read_buf_tail = (self->read_buf_tail + 1) % PYBUART_RX_BUFFER_LEN; return data; } else { // no buffering @@ -154,12 +142,11 @@ int uart_rx_char(pyb_uart_obj_t *self) { bool uart_tx_char(pyb_uart_obj_t *self, int c) { uint32_t timeout = 0; - while (!MAP_UARTCharPutNonBlocking(self->reg, c)) { - if (timeout++ > ((PYBUART_TX_MAX_TIMEOUT_MS * 1000) / PYBUART_TX_WAIT_US)) { + if (timeout++ > ((PYBUART_TX_MAX_TIMEOUT_MS * 1000) / PYBUART_TX_WAIT_US(self->baudrate))) { return false; } - UtilsDelay(UTILS_DELAY_US_TO_COUNT(PYBUART_TX_WAIT_US)); + UtilsDelay(UTILS_DELAY_US_TO_COUNT(PYBUART_TX_WAIT_US(self->baudrate))); } return true; } @@ -182,43 +169,28 @@ void uart_tx_strn_cooked(pyb_uart_obj_t *self, const char *str, uint len) { } } -mp_obj_t uart_callback_new (pyb_uart_obj_t *self, mp_obj_t handler, uint rxbuffer_size, mp_int_t priority) { +mp_obj_t uart_callback_new (pyb_uart_obj_t *self, mp_obj_t handler, mp_int_t priority, byte trigger) { // disable the uart interrupts before updating anything uart_callback_disable (self); if (self->uart_id == PYB_UART_0) { MAP_IntPrioritySet(INT_UARTA0, priority); MAP_UARTIntRegister(self->reg, UART0IntHandler); - } - else { + } else { MAP_IntPrioritySet(INT_UARTA1, priority); MAP_UARTIntRegister(self->reg, UART1IntHandler); } - // check the rx buffer size - if (rxbuffer_size > 0) { - // allocate the read buffer - self->read_buf_len = rxbuffer_size; - self->read_buf = m_new(byte, rxbuffer_size); - } - // create the callback mp_obj_t _callback = mpcallback_new ((mp_obj_t)self, handler, &uart_cb_methods, true); // enable the interrupts now + self->irq_trigger = trigger; uart_callback_enable (self); return _callback; } -void uart_disable_all (void) { - for (int i = 0; i < PYB_NUM_UARTS; i++) { - // in case it's not clocked - MAP_PRCMPeripheralClkEnable(pyb_uart_obj[i].peripheral, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK); - pyb_uart_deinit(&pyb_uart_obj[i]); - } -} - /****************************************************************************** DEFINE PRIVATE FUNCTIONS ******************************************************************************/ @@ -230,6 +202,12 @@ STATIC void uart_init (pyb_uart_obj_t *self) { // Reset the uart MAP_PRCMPeripheralReset(self->peripheral); + // re-allocate the read buffer after resetting the uart (which automatically disables any irqs) + self->read_buf_head = 0; + self->read_buf_tail = 0; + self->read_buf = MP_OBJ_NULL; // free the read buffer before allocating again + self->read_buf = m_new(byte, PYBUART_RX_BUFFER_LEN); + // Initialize the UART MAP_UARTConfigSetExpClk(self->reg, MAP_PRCMPeripheralClockGet(self->peripheral), self->baudrate, self->config); @@ -244,16 +222,17 @@ STATIC void uart_init (pyb_uart_obj_t *self) { UARTFlowControlSet(self->reg, self->flowcontrol); } -// Waits at most timeout milliseconds for at least 1 char to become ready for +// Waits at most timeout microseconds for at least 1 char to become ready for // reading (from buf or for direct reading). // Returns true if something available, false if not. -STATIC bool uart_rx_wait (pyb_uart_obj_t *self, uint32_t timeout) { +STATIC bool uart_rx_wait (pyb_uart_obj_t *self) { + int timeout = PYBUART_RX_TIMEOUT_US(self->baudrate); for ( ; ; ) { if (uart_rx_any(self)) { - return true; // have at least 1 char ready for reading + return true; // we have at least 1 char ready for reading } if (timeout > 0) { - HAL_Delay (1); + UtilsDelay(UTILS_DELAY_US_TO_COUNT(1)); timeout--; } else { @@ -277,8 +256,9 @@ STATIC void UARTGenericIntHandler(uint32_t uart_id) { // raise an exception when interrupts are finished mpexception_keyboard_nlr_jump(); } - else if (self->read_buf_len != 0) { - uint16_t next_head = (self->read_buf_head + 1) % self->read_buf_len; + // there's always a read buffer available + else { + uint16_t next_head = (self->read_buf_head + 1) % PYBUART_RX_BUFFER_LEN; if (next_head != self->read_buf_tail) { // only store data if room in buf self->read_buf[self->read_buf_head] = data; @@ -302,8 +282,11 @@ STATIC void UART1IntHandler(void) { STATIC void uart_callback_enable (mp_obj_t self_in) { pyb_uart_obj_t *self = self_in; - MAP_UARTIntClear(self->reg, UART_INT_RX | UART_INT_RT); - MAP_UARTIntEnable(self->reg, UART_INT_RX | UART_INT_RT); + // check for any of the rx interrupt types + if (self->irq_trigger & (E_UART_TRIGGER_RX_ANY | E_UART_TRIGGER_RX_HALF | E_UART_TRIGGER_RX_FULL)) { + MAP_UARTIntClear(self->reg, UART_INT_RX | UART_INT_RT); + MAP_UARTIntEnable(self->reg, UART_INT_RX | UART_INT_RT); + } } STATIC void uart_callback_disable (mp_obj_t self_in) { @@ -317,7 +300,7 @@ STATIC void uart_callback_disable (mp_obj_t self_in) { STATIC void pyb_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { pyb_uart_obj_t *self = self_in; if (self->baudrate > 0) { - mp_printf(print, "config & UART_CONFIG_PAR_MASK) == UART_CONFIG_PAR_EVEN ? 0 : 1); } - mp_printf(print, ", stop=%u, timeout=%u, timeout_char=%u, read_buf_len=%u>", - (self->config & UART_CONFIG_STOP_MASK) == UART_CONFIG_STOP_ONE ? 1 : 2, - self->timeout, self->timeout_char, self->read_buf_len); + mp_printf(print, ", stop=%u)", (self->config & UART_CONFIG_STOP_MASK) == UART_CONFIG_STOP_ONE ? 1 : 2); } else { - mp_printf(print, "", (self->uart_id + 1)); + mp_printf(print, "UART(%u)", self->uart_id); } } -/// \method init(baudrate, bits=8, parity=None, stop=1, *, timeout=1000, timeout_char=0) -/// -/// Initialise the UART bus with the given parameters: -/// -/// - `baudrate` is the clock rate. -/// - `bits` is the number of bits per byte, 5, 6, 7, 8 -/// - `parity` is the parity, `None`, 0 (even) or 1 (odd). -/// - `stop` is the number of stop bits, 1 or 2. -/// - `flow` is the flow control mode, `None`, `UART.RTS`, -/// `UART.CTS', or `UART.CTS | UART.RTS` -/// - `timeout` is the timeout (in milliseconds) when waiting for the first character. -/// - `timeout_char` is the timeout (in milliseconds) between characters. STATIC const mp_arg_t pyb_uart_init_args[] = { { MP_QSTR_baudrate, MP_ARG_REQUIRED | MP_ARG_INT, }, { MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, { MP_QSTR_parity, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_stop, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} }, - { MP_QSTR_flow, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_int = UART_FLOWCONTROL_NONE} }, - { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1000} }, - { MP_QSTR_timeout_char, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} }, + { MP_QSTR_pins, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, }; - STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { // parse args mp_arg_val_t args[MP_ARRAY_SIZE(pyb_uart_init_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(pyb_uart_init_args), pyb_uart_init_args, args); - // set timeouts - self->timeout = args[5].u_int; - self->timeout_char = args[6].u_int; - - // no read buffer for the moment - self->read_buf_head = 0; - self->read_buf_tail = 0; - self->read_buf_len = 0; - self->read_buf = NULL; - // get the baudrate - self->baudrate = args[0].u_int; - - // set the UART configuration values - if (n_args > 1) { - switch (args[1].u_int) { - case 5: - self->config = UART_CONFIG_WLEN_5; - break; - case 6: - self->config = UART_CONFIG_WLEN_6; - break; - case 7: - self->config = UART_CONFIG_WLEN_7; - break; - case 8: - self->config = UART_CONFIG_WLEN_8; - break; - default: - goto error; - break; - } - // Parity - if (args[2].u_obj == mp_const_none) { - self->config |= UART_CONFIG_PAR_NONE; + if (args[0].u_int <= 0) { + goto error; + } + uint baudrate = args[0].u_int; + uint config; + switch (args[1].u_int) { + case 5: + config = UART_CONFIG_WLEN_5; + break; + case 6: + config = UART_CONFIG_WLEN_6; + break; + case 7: + config = UART_CONFIG_WLEN_7; + break; + case 8: + config = UART_CONFIG_WLEN_8; + break; + default: + goto error; + break; + } + // parity + if (args[2].u_obj == mp_const_none) { + config |= UART_CONFIG_PAR_NONE; + } else { + config |= ((mp_obj_get_int(args[2].u_obj) & 1) ? UART_CONFIG_PAR_ODD : UART_CONFIG_PAR_EVEN); + } + // stop bits + config |= (args[3].u_int == 1 ? UART_CONFIG_STOP_ONE : UART_CONFIG_STOP_TWO); + + mp_obj_t pins_o = args[4].u_obj; + uint flowcontrol = UART_FLOWCONTROL_NONE; + if (pins_o != mp_const_none) { + if (pins_o == MP_OBJ_NULL) { + // use the default pins + pin_config (pyb_uart_def_pin[self->uart_id][PIN_TYPE_UART_TX].pin, pyb_uart_def_pin[self->uart_id][PIN_TYPE_UART_TX].af_idx, + 0, PIN_TYPE_STD_PU, -1, PIN_STRENGTH_2MA); + pin_config (pyb_uart_def_pin[self->uart_id][PIN_TYPE_UART_RX].pin, pyb_uart_def_pin[self->uart_id][PIN_TYPE_UART_RX].af_idx, + 0, PIN_TYPE_STD_PU, -1, PIN_STRENGTH_2MA); } else { - self->config |= ((mp_obj_get_int(args[2].u_obj) & 1) ? UART_CONFIG_PAR_ODD : UART_CONFIG_PAR_EVEN); - } - // Stop bits - self->config |= (args[3].u_int == 1 ? UART_CONFIG_STOP_ONE : UART_CONFIG_STOP_TWO); - // Flow control - if (args[4].u_int != UART_FLOWCONTROL_NONE || args[4].u_int != UART_FLOWCONTROL_TX || - args[4].u_int != UART_FLOWCONTROL_RX || args[4].u_int != (UART_FLOWCONTROL_TX | UART_FLOWCONTROL_RX)) { - goto error; + mp_obj_t *pins_t; + mp_uint_t n_pins; + mp_obj_get_array(pins_o, &n_pins, &pins_t); + if (n_pins != 2 && n_pins != 4) { + goto error; + } + if (n_pins == 4) { + if (pins_t[PIN_TYPE_UART_RTS] != mp_const_none && pins_t[PIN_TYPE_UART_RX] == mp_const_none) { + goto error; // RTS pin given in TX only mode + } else if (pins_t[PIN_TYPE_UART_CTS] != mp_const_none && pins_t[PIN_TYPE_UART_TX] == mp_const_none) { + goto error; // CTS pin given in RX only mode + } else { + if (pins_t[PIN_TYPE_UART_RTS] != mp_const_none) { + flowcontrol |= UART_FLOWCONTROL_RX; + } + if (pins_t[PIN_TYPE_UART_CTS] != mp_const_none) { + flowcontrol |= UART_FLOWCONTROL_TX; + } + } + } + // the pins tuple passed looks good so far + for (int i = 0; i < n_pins; i++) { + if (pins_t[i] != mp_const_none) { + pin_obj_t *pin = pin_find(pins_t[i]); + pin_config (pin, pin_find_af_index(pin, PIN_FN_UART, self->uart_id, i), + 0, PIN_TYPE_STD_PU, -1, PIN_STRENGTH_2MA); + } + } } - self->flowcontrol = args[4].u_int; - } - else { - self->config = UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE; - self->flowcontrol = UART_FLOWCONTROL_NONE; } + self->baudrate = baudrate; + self->config = config; + self->flowcontrol = flowcontrol; + // initialize and enable the uart uart_init (self); // register it with the sleep module @@ -438,25 +429,12 @@ error: nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); } -/// \classmethod \constructor(bus, ...) -/// -/// Construct a UART object on the given bus id. `bus id` can be 1 or 2 -/// With no additional parameters, the UART object is created but not -/// initialised (it has the settings from the last initialisation of -/// the bus, if any). -/// When only the baud rate is given the UART object is created and -/// initialized with the default configuration of: 8 bit transfers, -/// 1 stop bit, no parity and flow control disabled. -/// See `init` for parameters of initialisation. -/// If extra arguments are given, the bus is initialised with these arguments -/// See `init` for parameters of initialisation. -/// STATIC mp_obj_t pyb_uart_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { // check arguments mp_arg_check_num(n_args, n_kw, 1, MP_ARRAY_SIZE(pyb_uart_init_args), true); // work out the uart id - int32_t uart_id = mp_obj_get_int(args[0]) - 1; + int32_t uart_id = mp_obj_get_int(args[0]); if (uart_id < PYB_UART_0 || uart_id > PYB_UART_1) { nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable)); @@ -482,8 +460,6 @@ STATIC mp_obj_t pyb_uart_init(mp_uint_t n_args, const mp_obj_t *args, mp_map_t * } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_uart_init_obj, 1, pyb_uart_init); -/// \method deinit() -/// Turn off the UART bus. STATIC mp_obj_t pyb_uart_deinit(mp_obj_t self_in) { pyb_uart_obj_t *self = self_in; @@ -491,6 +467,8 @@ STATIC mp_obj_t pyb_uart_deinit(mp_obj_t self_in) { pybsleep_remove (self); // invalidate the baudrate self->baudrate = 0; + // free the read buffer + m_del(byte, self->read_buf, PYBUART_RX_BUFFER_LEN); MAP_UARTIntDisable(self->reg, UART_INT_RX | UART_INT_RT); MAP_UARTDisable(self->reg); MAP_PRCMPeripheralClkDisable(self->peripheral, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK); @@ -498,21 +476,22 @@ STATIC mp_obj_t pyb_uart_deinit(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_deinit_obj, pyb_uart_deinit); -/// \method any() -/// Return `True` if any characters waiting, else `False`. STATIC mp_obj_t pyb_uart_any(mp_obj_t self_in) { pyb_uart_obj_t *self = self_in; - if (uart_rx_any(self)) { - return mp_const_true; - } else { - return mp_const_false; - } + return mp_obj_new_int(uart_rx_any(self)); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_any_obj, pyb_uart_any); -/// \method callback(handler, value, priority) -/// Creates a callback object associated with the uart -/// min num of arguments is 1 (value). The value is the size of the rx buffer +STATIC mp_obj_t pyb_uart_sendbreak(mp_obj_t self_in) { + pyb_uart_obj_t *self = self_in; + // send a break signal for at least 2 complete frames + MAP_UARTBreakCtl(self->reg, true); + UtilsDelay(UTILS_DELAY_US_TO_COUNT(PYBUART_2_FRAMES_TIME_US(self->baudrate))); + MAP_UARTBreakCtl(self->reg, false); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_sendbreak_obj, pyb_uart_sendbreak); + STATIC mp_obj_t pyb_uart_callback (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { mp_arg_val_t args[mpcallback_INIT_NUM_ARGS]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, mpcallback_INIT_NUM_ARGS, mpcallback_init_args, args); @@ -531,6 +510,7 @@ STATIC mp_obj_t pyb_uart_callback (mp_uint_t n_args, const mp_obj_t *pos_args, m } // register a new callback + // FIXME triggers!! return uart_callback_new (self, args[1].u_obj, mp_obj_get_int(args[3].u_obj), priority); } else if (!_callback) { _callback = mpcallback_new (self, mp_const_none, &uart_cb_methods, false); @@ -539,55 +519,12 @@ STATIC mp_obj_t pyb_uart_callback (mp_uint_t n_args, const mp_obj_t *pos_args, m } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_uart_callback_obj, 1, pyb_uart_callback); -/// \method writechar(char) -/// Write a single character on the bus. `char` is an integer to write. -/// Return value: `None`. -STATIC mp_obj_t pyb_uart_writechar(mp_obj_t self_in, mp_obj_t char_in) { - pyb_uart_obj_t *self = self_in; - - // get the character to write - uint8_t data = mp_obj_get_int(char_in); - - // send the character - if (!uart_tx_char(self, data)) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed)); - } - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_uart_writechar_obj, pyb_uart_writechar); - -/// \method readchar() -/// Receive a single character on the bus. -/// Return value: The character read, as an integer. Returns -1 on timeout. -STATIC mp_obj_t pyb_uart_readchar(mp_obj_t self_in) { - pyb_uart_obj_t *self = self_in; - if (uart_rx_wait(self, self->timeout)) { - return mp_obj_new_int(uart_rx_char(self)); - } else { - // return -1 on timeout - return MP_OBJ_NEW_SMALL_INT(-1); - } -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_readchar_obj, pyb_uart_readchar); - -/// \method sendbreak() -STATIC mp_obj_t pyb_uart_sendbreak(mp_obj_t self_in) { - pyb_uart_obj_t *self = self_in; - // send a break signal for at least 2 complete frames - MAP_UARTBreakCtl(self->reg, true); - UtilsDelay(UTILS_DELAY_US_TO_COUNT((22 * 1000000) / self->baudrate)); - MAP_UARTBreakCtl(self->reg, false); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_sendbreak_obj, pyb_uart_sendbreak); - - STATIC const mp_map_elem_t pyb_uart_locals_dict_table[] = { // instance methods { MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pyb_uart_init_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_deinit), (mp_obj_t)&pyb_uart_deinit_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_any), (mp_obj_t)&pyb_uart_any_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_sendbreak), (mp_obj_t)&pyb_uart_sendbreak_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_callback), (mp_obj_t)&pyb_uart_callback_obj }, /// \method read([nbytes]) @@ -601,13 +538,8 @@ STATIC const mp_map_elem_t pyb_uart_locals_dict_table[] = { /// \method write(buf) { MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_stream_write_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_writechar), (mp_obj_t)&pyb_uart_writechar_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_readchar), (mp_obj_t)&pyb_uart_readchar_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_sendbreak), (mp_obj_t)&pyb_uart_sendbreak_obj }, - // class constants - { MP_OBJ_NEW_QSTR(MP_QSTR_CTS), MP_OBJ_NEW_SMALL_INT(UART_FLOWCONTROL_TX) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_RTS), MP_OBJ_NEW_SMALL_INT(UART_FLOWCONTROL_RX) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_RX_ANY), MP_OBJ_NEW_SMALL_INT(E_UART_TRIGGER_RX_ANY) }, }; STATIC MP_DEFINE_CONST_DICT(pyb_uart_locals_dict, pyb_uart_locals_dict_table); @@ -622,7 +554,7 @@ STATIC mp_uint_t pyb_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, i } // wait for first char to become available - if (!uart_rx_wait(self, self->timeout)) { + if (!uart_rx_wait(self)) { // we can either return 0 to indicate EOF (then read() method returns b'') // or return EAGAIN error to indicate non-blocking (then read() method returns None) return 0; @@ -632,7 +564,7 @@ STATIC mp_uint_t pyb_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, i byte *orig_buf = buf; for ( ; ; ) { *buf++ = uart_rx_char(self); - if (--size == 0 || !uart_rx_wait(self, self->timeout_char)) { + if (--size == 0 || !uart_rx_wait(self)) { // return number of bytes read return buf - orig_buf; } diff --git a/cc3200/mods/pybuart.h b/cc3200/mods/pybuart.h index 66812a8834..476fc11a4e 100644 --- a/cc3200/mods/pybuart.h +++ b/cc3200/mods/pybuart.h @@ -28,6 +28,12 @@ #ifndef PYBUART_H_ #define PYBUART_H_ +// interrupt triggers +#define E_UART_TRIGGER_RX_ANY (0x01) +#define E_UART_TRIGGER_RX_HALF (0x02) +#define E_UART_TRIGGER_RX_FULL (0x04) +#define E_UART_TRIGGER_TX_DONE (0x08) + typedef enum { PYB_UART_0 = 0, PYB_UART_1 = 1, @@ -38,12 +44,11 @@ typedef struct _pyb_uart_obj_t pyb_uart_obj_t; extern const mp_obj_type_t pyb_uart_type; void uart_init0(void); -bool uart_rx_any(pyb_uart_obj_t *uart_obj); +uint32_t uart_rx_any(pyb_uart_obj_t *uart_obj); int uart_rx_char(pyb_uart_obj_t *uart_obj); bool uart_tx_char(pyb_uart_obj_t *self, int c); bool uart_tx_strn(pyb_uart_obj_t *uart_obj, const char *str, uint len); void uart_tx_strn_cooked(pyb_uart_obj_t *uart_obj, const char *str, uint len); -mp_obj_t uart_callback_new (pyb_uart_obj_t *self, mp_obj_t handler, uint rxbuffer_size, mp_int_t priority); -void uart_disable_all (void); +mp_obj_t uart_callback_new (pyb_uart_obj_t *self, mp_obj_t handler, mp_int_t priority, byte trigger); #endif // PYBUART_H_ diff --git a/cc3200/mpconfigport.h b/cc3200/mpconfigport.h index 41dc27eaec..c6397c1f8f 100644 --- a/cc3200/mpconfigport.h +++ b/cc3200/mpconfigport.h @@ -148,6 +148,7 @@ extern const struct _mp_obj_module_t mp_module_ussl; mp_obj_list_t pybsleep_obj_list; \ mp_obj_list_t mpcallback_obj_list; \ mp_obj_list_t pyb_timer_channel_obj_list; \ + struct _pyb_uart_obj_t *pyb_uart_objs[2]; \ // type definitions for the specific machine diff --git a/cc3200/mptask.c b/cc3200/mptask.c index a96bd1b93d..87990b43c2 100644 --- a/cc3200/mptask.c +++ b/cc3200/mptask.c @@ -139,18 +139,13 @@ soft_reset: #endif #ifdef LAUNCHXL - // configure the stdio uart pins with the correct alternate functions - // param 3 ("mode") is DON'T CARE" for AFs others than GPIO - pin_config ((pin_obj_t *)&MICROPY_STDIO_UART_TX_PIN, MICROPY_STDIO_UART_TX_PIN_AF, 0, PIN_TYPE_STD_PU, -1, PIN_STRENGTH_2MA); - pin_config ((pin_obj_t *)&MICROPY_STDIO_UART_RX_PIN, MICROPY_STDIO_UART_RX_PIN_AF, 0, PIN_TYPE_STD_PU, -1, PIN_STRENGTH_2MA); - // instantiate the stdio uart + // instantiate the stdio uart on the default pins mp_obj_t args[2] = { mp_obj_new_int(MICROPY_STDIO_UART), mp_obj_new_int(MICROPY_STDIO_UART_BAUD), }; pyb_stdio_uart = pyb_uart_type.make_new((mp_obj_t)&pyb_uart_type, MP_ARRAY_SIZE(args), 0, args); - // create a callback for the uart, in order to enable the rx interrupts - uart_callback_new (pyb_stdio_uart, mp_const_none, MICROPY_STDIO_UART_RX_BUF_SIZE, INT_PRIORITY_LVL_3); + uart_callback_new (pyb_stdio_uart, mp_const_none, INT_PRIORITY_LVL_3, E_UART_TRIGGER_RX_ANY); #else pyb_stdio_uart = MP_OBJ_NULL; #endif @@ -239,10 +234,9 @@ soft_reset_exit: pybsleep_signal_soft_reset(); mp_printf(&mp_plat_print, "PYB: soft reboot\n"); - // disable all peripherals that could trigger a callback - pyb_rtc_callback_disable(NULL); - timer_disable_all(); - uart_disable_all(); + // disable all callbacks to avoid undefined behaviour + // when coming out of a soft reset + mpcallback_disable_all(); // flush the serial flash buffer sflash_disk_flush(); diff --git a/cc3200/qstrdefsport.h b/cc3200/qstrdefsport.h index d3ef06d8d6..73096d9adf 100644 --- a/cc3200/qstrdefsport.h +++ b/cc3200/qstrdefsport.h @@ -61,6 +61,7 @@ Q(flush) Q(FileIO) Q(enable) Q(disable) +Q(repl_uart) // Entries for sys.path Q(/flash) Q(/flash/lib) @@ -119,6 +120,7 @@ Q(mode) Q(pull) Q(drive) Q(alt) +Q(alt_list) Q(IN) Q(OUT) Q(OPEN_DRAIN) @@ -137,24 +139,16 @@ Q(IRQ_HIGH_LEVEL) // for UART class Q(UART) +Q(init) +Q(deinit) +Q(any) +Q(sendbreak) Q(baudrate) Q(bits) Q(stop) Q(parity) -Q(init) -Q(deinit) -Q(all) -Q(writechar) -Q(readchar) -Q(sendbreak) -Q(readinto) -Q(read_buf_len) -Q(timeout) -Q(timeout_char) -Q(repl_uart) -Q(flow) -Q(RTS) -Q(CTS) +Q(pins) +Q(RX_ANY) // for I2C class Q(I2C) diff --git a/docs/library/pyb.UART.rst b/docs/library/pyb.UART.rst index 01a04ef4e1..b57a93873d 100644 --- a/docs/library/pyb.UART.rst +++ b/docs/library/pyb.UART.rst @@ -36,17 +36,25 @@ using the standard stream methods:: uart.readinto(buf) # read and store into the given buffer uart.write('abc') # write the 3 characters -Individual characters can be read/written using:: +.. only:: port_pyboard + + Individual characters can be read/written using:: + + uart.readchar() # read 1 character and returns it as an integer + uart.writechar(42) # write 1 character + + To check if there is anything to be read, use:: - uart.readchar() # read 1 character and returns it as an integer - uart.writechar(42) # write 1 character + uart.any() # returns True if any characters waiting -To check if there is anything to be read, use:: + *Note:* The stream functions ``read``, ``write``, etc. are new in MicroPython v1.3.4. + Earlier versions use ``uart.send`` and ``uart.recv``. - uart.any() # returns True if any characters waiting +.. only:: port_wipy + + To check if there is anything to be read, use:: -*Note:* The stream functions ``read``, ``write``, etc. are new in MicroPython v1.3.4. -Earlier versions use ``uart.send`` and ``uart.recv``. + uart.any() # returns the number of characters available for reading Constructors ------------ @@ -73,7 +81,7 @@ Constructors .. class:: pyb.UART(bus, ...) - Construct a UART object on the given bus. ``bus`` can be 1 or 2. + Construct a UART object on the given bus. ``bus`` can be 0 or 1. With no additional parameters, the UART object is created but not initialised (it has the settings from the last initialisation of the bus, if any). If extra arguments are given, the bus is initialised. @@ -110,7 +118,7 @@ Methods .. only:: port_wipy - .. method:: uart.init(baudrate, bits=8, parity=None, stop=1, \*, timeout=1000, flow=None, timeout_char=0) + .. method:: uart.init(baudrate, bits=8, parity=None, stop=1, \*, pins=(TX, RX, RTS, CTS)) Initialise the UART bus with the given parameters: @@ -118,18 +126,27 @@ Methods - ``bits`` is the number of bits per character, 7, 8 or 9. - ``parity`` is the parity, ``None``, 0 (even) or 1 (odd). - ``stop`` is the number of stop bits, 1 or 2. - - ``flow`` sets the flow control type. Can be None, ``UART.RTS``, ``UART.CTS`` - or ``UART.RTS | UART.CTS``. - - ``timeout`` is the timeout in milliseconds to wait for the first character. - - ``timeout_char`` is the timeout in milliseconds to wait between characters. + - ``pins`` is a 4 or 2 item list indicating the TX, RX, RTS and CTS pins (in that order). + Any of the pins can be None if one wants the UART to operate with limited functionality. + If the RTS pin is given the the RX pin must be given as well. The same applies to CTS. + When no pins are given, then the default set of TX and RX pins is taken, and hardware + flow control will be disabled. If pins=None, no pin assignment will be made. .. method:: uart.deinit() Turn off the UART bus. -.. method:: uart.any() +.. only:: port_pyboard + + .. method:: uart.any() + + Return ``True`` if any characters waiting, else ``False``. + +.. only:: port_wipy + + .. method:: uart.any() - Return ``True`` if any characters waiting, else ``False``. + Return the number of characters available for reading. .. method:: uart.read([nbytes]) @@ -144,7 +161,7 @@ Methods on timeout. .. only:: port_wipy - + Return value: a bytes object containing the bytes read in. Returns ``b''`` on timeout. @@ -184,17 +201,17 @@ Methods Return value: number of bytes written. + .. method:: uart.writechar(char) + + Write a single character on the bus. ``char`` is an integer to write. + Return value: ``None``. + .. only:: port_wipy Write the buffer of bytes to the bus. Return value: number of bytes written. -.. method:: uart.writechar(char) - - Write a single character on the bus. ``char`` is an integer to write. - Return value: ``None``. - .. method:: uart.sendbreak() Send a break condition on the bus. This drives the bus low for a duration @@ -229,7 +246,15 @@ Methods Constants --------- -.. data:: UART.RTS -.. data:: UART.CTS - - to select the flow control type +.. only:: port_pyboard + + .. data:: UART.RTS + .. data:: UART.CTS + + to select the flow control type + +.. only:: port_wipy + + .. data:: UART.RX_ANY + + IRQ trigger sources diff --git a/tests/wipy/pin.py b/tests/wipy/pin.py index 39a52ca018..20bea3e5a7 100644 --- a/tests/wipy/pin.py +++ b/tests/wipy/pin.py @@ -5,7 +5,6 @@ from pyb import Pin import os machine = os.uname().machine - if 'LaunchPad' in machine: pin_map = ['GP24', 'GP12', 'GP14', 'GP15', 'GP16', 'GP17', 'GP28', 'GP8', 'GP6', 'GP30', 'GP31', 'GP3', 'GP0', 'GP4', 'GP5'] af_range = range(1, 16) @@ -24,7 +23,7 @@ def test_pin_read(pull): # enable the pull resistor on all pins, then read the value for p in pin_map: pin = Pin(p, mode=Pin.IN, pull=pull) - # read the pin value + for p in pin_map: print(pin()) def test_pin_af(): diff --git a/tests/wipy/uart.py b/tests/wipy/uart.py new file mode 100644 index 0000000000..82bbe8a38b --- /dev/null +++ b/tests/wipy/uart.py @@ -0,0 +1,87 @@ +''' +UART test fro the CC3200 based boards. +UART0 and UART1 must be connected together for this test to pass. +''' + +from pyb import UART +from pyb import Pin +import os + +machine = os.uname().machine +if 'LaunchPad' in machine: + uart_id_range = range(0, 2) + uart_pins = [[('GP12', 'GP13'), ('GP12', 'GP13', 'GP7', 'GP6')], [('GP16', 'GP17'), ('GP16', 'GP17', 'GP7', 'GP6')]] +elif 'WiPy' in machine: + uart_id_range = range(0, 2) + uart_pins = [[('GP12', 'GP13'), ('GP12', 'GP13', 'GP7', 'GP6')], [('GP16', 'GP17'), ('GP16', 'GP17', 'GP7', 'GP6')]] +else: + raise Exception('Board not supported!') + +for uart_id in uart_id_range: + uart = UART(uart_id, 38400) + print(uart) + uart.init(baudrate=57600, stop=1, parity=None, pins=uart_pins[uart_id][0]) + uart.init(baudrate=9600, stop=2, parity=0, pins=uart_pins[uart_id][1]) + uart.init(baudrate=115200, parity=1, pins=uart_pins[uart_id][0]) + uart.sendbreak() + +# assign GP1, GP2, GP3 and GP4 back to GPIO mode +Pin('GP1', mode=Pin.IN) +Pin('GP2', mode=Pin.IN) +Pin('GP3', mode=Pin.IN) +Pin('GP4', mode=Pin.IN) + +# now it's time for some loopback tests between the uarts +uart0 = UART(0, 1000000, pins=uart_pins[0][0]) +print(uart0) +uart1 = UART(1, 1000000, pins=uart_pins[1][0]) +print(uart1) + +print(uart0.write(b'123456') == 6) +print(uart1.read() == b'123456') + +print(uart1.write(b'123') == 3) +print(uart0.read(1) == b'1') +print(uart0.read(2) == b'23') +print(uart0.read() == b'') + +uart0.write(b'123') +buf = bytearray(3) +print(uart1.readinto(buf, 1) == 1) +print(buf) +print(uart1.readinto(buf) == 2) +print(buf) + +uart0.write(b'123') +print(uart1.any() > 0) +print(uart1.readline() == b'123') +print(uart1.any() == 0) + +uart0.write(b'1234567890') +print(uart1.readall() == b'1234567890') + +# tx only mode +Pin('GP13', mode=Pin.IN) +uart0 = UART(0, 1000000, pins=('GP12', None)) +print(uart0.write(b'123456') == 6) +print(uart1.read() == b'123456') +print(uart1.write(b'123') == 3) +print(uart0.read() == b'') + +# rx only mode +Pin('GP12', mode=Pin.IN) +uart0 = UART(0, 1000000, pins=(None, 'GP13')) +print(uart0.write(b'123456') == 6) +print(uart1.read() == b'') +print(uart1.write(b'123') == 3) +print(uart0.read() == b'123') + +# next ones must raise +try: + UART(0, 9600, parity=2, pins=('GP12', 'GP13', 'GP7')) +except Exception: + print('Exception') +try: + UART(0, 9600, parity=2, pins=('GP12', 'GP7')) +except Exception: + print('Exception') diff --git a/tests/wipy/uart.py.exp b/tests/wipy/uart.py.exp new file mode 100644 index 0000000000..ad80a3513a --- /dev/null +++ b/tests/wipy/uart.py.exp @@ -0,0 +1,28 @@ +UART(0, baudrate=38400, bits=8, parity=None, stop=1) +UART(1, baudrate=38400, bits=8, parity=None, stop=1) +UART(0, baudrate=1000000, bits=8, parity=None, stop=1) +UART(1, baudrate=1000000, bits=8, parity=None, stop=1) +True +True +True +True +True +True +True +bytearray(b'1\x00\x00') +True +bytearray(b'23\x00') +True +True +True +True +True +True +True +True +True +True +True +True +Exception +Exception