From 2d717ad97a48c9451a2a51096904f471a0af0a60 Mon Sep 17 00:00:00 2001 From: Daniel Campora Date: Thu, 26 Mar 2015 10:25:28 +0100 Subject: [PATCH] cc3200: Add callback support to the UART for RX interrupts. --- cc3200/boards/LAUNCHXL/mpconfigboard.h | 1 + cc3200/boards/WIPY-SD/mpconfigboard.h | 1 + cc3200/boards/WIPY/mpconfigboard.h | 1 + cc3200/misc/mpcallback.c | 2 +- cc3200/mods/modwlan.c | 8 +- cc3200/mods/pybi2c.c | 13 +- cc3200/mods/pybpin.c | 8 +- cc3200/mods/pybrtc.c | 8 +- cc3200/mods/pybspi.c | 13 +- cc3200/mods/pybuart.c | 187 ++++++++++++++----------- cc3200/mods/pybuart.h | 1 + cc3200/mptask.c | 7 +- cc3200/qstrdefsport.h | 3 +- 13 files changed, 143 insertions(+), 110 deletions(-) diff --git a/cc3200/boards/LAUNCHXL/mpconfigboard.h b/cc3200/boards/LAUNCHXL/mpconfigboard.h index 9fcccc8e8b..982a15c2ff 100644 --- a/cc3200/boards/LAUNCHXL/mpconfigboard.h +++ b/cc3200/boards/LAUNCHXL/mpconfigboard.h @@ -36,6 +36,7 @@ #define MICROPY_STDIO_UART PYB_UART_0 #define MICROPY_STDIO_UART_BAUD 115200 +#define MICROPY_STDIO_UART_RX_BUF_SIZE 128 #define MICROPY_SYS_LED_PRCM PRCM_GPIOA1 #define MICROPY_SAFE_BOOT_PRCM PRCM_GPIOA2 diff --git a/cc3200/boards/WIPY-SD/mpconfigboard.h b/cc3200/boards/WIPY-SD/mpconfigboard.h index ab920b7182..27de4b8aad 100644 --- a/cc3200/boards/WIPY-SD/mpconfigboard.h +++ b/cc3200/boards/WIPY-SD/mpconfigboard.h @@ -36,6 +36,7 @@ #define MICROPY_STDIO_UART PYB_UART_0 #define MICROPY_STDIO_UART_BAUD 115200 +#define MICROPY_STDIO_UART_RX_BUF_SIZE 128 #define MICROPY_SYS_LED_PRCM PRCM_GPIOA3 #define MICROPY_SAFE_BOOT_PRCM PRCM_GPIOA3 diff --git a/cc3200/boards/WIPY/mpconfigboard.h b/cc3200/boards/WIPY/mpconfigboard.h index 700e343041..415038cd3e 100644 --- a/cc3200/boards/WIPY/mpconfigboard.h +++ b/cc3200/boards/WIPY/mpconfigboard.h @@ -36,6 +36,7 @@ #define MICROPY_STDIO_UART PYB_UART_0 #define MICROPY_STDIO_UART_BAUD 115200 +#define MICROPY_STDIO_UART_RX_BUF_SIZE 128 #define MICROPY_SYS_LED_PRCM PRCM_GPIOA3 #define MICROPY_SAFE_BOOT_PRCM PRCM_GPIOA3 diff --git a/cc3200/misc/mpcallback.c b/cc3200/misc/mpcallback.c index 7827b0e62e..c7690dca4c 100644 --- a/cc3200/misc/mpcallback.c +++ b/cc3200/misc/mpcallback.c @@ -45,7 +45,7 @@ const mp_arg_t mpcallback_init_args[] = { { MP_QSTR_handler, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_priority, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} }, { MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_wake, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = PYB_PWR_MODE_ACTIVE} }, + { MP_QSTR_wakes, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = PYB_PWR_MODE_ACTIVE} }, }; /****************************************************************************** diff --git a/cc3200/mods/modwlan.c b/cc3200/mods/modwlan.c index 9650161768..7995c65e87 100644 --- a/cc3200/mods/modwlan.c +++ b/cc3200/mods/modwlan.c @@ -911,17 +911,17 @@ STATIC mp_obj_t wlan_scan(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(wlan_scan_obj, wlan_scan); -/// \method callback(handler, intmode, value, priority, pwrmode) +/// \method callback(handler, pwrmode) /// Creates a callback object associated with WLAN /// min num of arguments is 1 (pwrmode) STATIC mp_obj_t wlan_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); - wlan_obj_t *self = pos_args[0]; - mp_obj_t _callback = mpcallback_find(self); + wlan_obj_t *self = pos_args[0]; + mp_obj_t _callback = mpcallback_find(self); // check if any parameters were passed - if (kw_args->used > 0 || _callback == mp_const_none) { + if (kw_args->used > 0 || !_callback) { // check the power mode if (args[4].u_int != PYB_PWR_MODE_LPDS) { // throw an exception since WLAN only supports LPDS mode diff --git a/cc3200/mods/pybi2c.c b/cc3200/mods/pybi2c.c index 5b22c653d8..6fd58b0c07 100644 --- a/cc3200/mods/pybi2c.c +++ b/cc3200/mods/pybi2c.c @@ -129,13 +129,6 @@ STATIC void i2c_init (pyb_i2c_obj_t *self) { MAP_I2CMasterInitExpClk(I2CA0_BASE, self->baudrate); } -STATIC void i2c_deinit(void) { - MAP_I2CMasterDisable(I2CA0_BASE); - MAP_PRCMPeripheralClkDisable(PRCM_I2CA0, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK); - // invalidate the baudrate - pyb_i2c_obj.baudrate = 0; -} - STATIC bool pyb_i2c_transaction(uint cmd) { // Convert the timeout to microseconds int32_t timeout = PYBI2C_TRANSC_TIMEOUT_MS * 1000; @@ -319,7 +312,11 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_i2c_init_obj, pyb_i2c_init); /// \method deinit() /// Turn off the I2C bus. STATIC mp_obj_t pyb_i2c_deinit(mp_obj_t self_in) { - i2c_deinit(); + // disable the peripheral + MAP_I2CMasterDisable(I2CA0_BASE); + MAP_PRCMPeripheralClkDisable(PRCM_I2CA0, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK); + // invalidate the baudrate + pyb_i2c_obj.baudrate = 0; // unregister it with the sleep module pybsleep_remove ((const mp_obj_t)self_in); return mp_const_none; diff --git a/cc3200/mods/pybpin.c b/cc3200/mods/pybpin.c index aba4f65fed..2cbd615356 100644 --- a/cc3200/mods/pybpin.c +++ b/cc3200/mods/pybpin.c @@ -617,7 +617,7 @@ STATIC mp_obj_t pin_af(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_af_obj, pin_af); -/// \method callback(method, intmode, value, priority, pwrmode) +/// \method callback(method, intmode, priority, pwrmode) /// Creates a callback object associated to a pin /// min num of arguments is 1 (intmode) STATIC mp_obj_t pin_callback (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { @@ -627,7 +627,7 @@ STATIC mp_obj_t pin_callback (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map pin_obj_t *self = pos_args[0]; // check if any parameters were passed mp_obj_t _callback = mpcallback_find(self); - if (kw_args->used > 0 || _callback == mp_const_none) { + if (kw_args->used > 0 || !_callback) { // convert the priority to the correct value uint priority = mpcallback_translate_priority (args[2].u_int); // verify the interrupt mode @@ -840,8 +840,6 @@ STATIC void EXTI_Handler(uint port) { pin_obj_t *self = (pin_obj_t *)pin_find_pin_by_port_bit(&pin_cpu_pins_locals_dict, port, bit); mp_obj_t _callback = mpcallback_find(self); - if (_callback) { - mpcallback_handler(_callback); - } + mpcallback_handler(_callback); } diff --git a/cc3200/mods/pybrtc.c b/cc3200/mods/pybrtc.c index 4d22c85f76..9c42222bc4 100644 --- a/cc3200/mods/pybrtc.c +++ b/cc3200/mods/pybrtc.c @@ -179,7 +179,7 @@ mp_obj_t pyb_rtc_datetime(mp_uint_t n_args, const mp_obj_t *args) { } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_datetime_obj, 1, 2, pyb_rtc_datetime); -/// \method callback(handler, intmode, value, priority, pwrmode) +/// \method callback(handler, value, pwrmode) /// Creates a callback object associated with the real time clock /// min num of arguments is 1 (value). The value is the alarm time /// in the future, in msec @@ -189,7 +189,7 @@ STATIC mp_obj_t pyb_rtc_callback (mp_uint_t n_args, const mp_obj_t *pos_args, mp // check if any parameters were passed mp_obj_t _callback = mpcallback_find((mp_obj_t)&pyb_rtc_obj); - if (kw_args->used > 0 || _callback == mp_const_none) { + if (kw_args->used > 0 || !_callback) { uint32_t f_mseconds = args[3].u_int; uint32_t seconds; uint16_t mseconds; @@ -201,6 +201,10 @@ STATIC mp_obj_t pyb_rtc_callback (mp_uint_t n_args, const mp_obj_t *pos_args, mp seconds += f_mseconds / 1000; mseconds += f_mseconds - ((f_mseconds / 1000) * 1000); + // disable the interrupt before updating anything + // (the object is not relevant here, the function already knows it) + pyb_rtc_callback_disable(NULL); + // set the match value MAP_PRCMRTCMatchSet(seconds, mseconds); diff --git a/cc3200/mods/pybspi.c b/cc3200/mods/pybspi.c index 75a43ea310..ceddd22804 100644 --- a/cc3200/mods/pybspi.c +++ b/cc3200/mods/pybspi.c @@ -110,13 +110,6 @@ STATIC void pybspi_init (const pyb_spi_obj_t *self) { MAP_SPIEnable(GSPI_BASE); } -STATIC void pybspi_deinit(void) { - MAP_SPIDisable(GSPI_BASE); - MAP_PRCMPeripheralClkDisable(PRCM_GSPI, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK); - // invalidate the baudrate - pyb_spi_obj.baudrate = 0; -} - STATIC void pybspi_tx (pyb_spi_obj_t *self, const void *data) { uint32_t txdata = 0xFFFFFFFF; if (data) { @@ -278,7 +271,11 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_init_obj, 1, pyb_spi_init); /// \method deinit() /// Turn off the spi bus. STATIC mp_obj_t pyb_spi_deinit(mp_obj_t self_in) { - pybspi_deinit(); + // disable the peripheral + MAP_SPIDisable(GSPI_BASE); + MAP_PRCMPeripheralClkDisable(PRCM_GSPI, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK); + // invalidate the baudrate + pyb_spi_obj.baudrate = 0; // unregister it with the sleep module pybsleep_remove((const mp_obj_t)self_in); return mp_const_none; diff --git a/cc3200/mods/pybuart.c b/cc3200/mods/pybuart.c index 06854b79b6..408e2a4194 100644 --- a/cc3200/mods/pybuart.c +++ b/cc3200/mods/pybuart.c @@ -47,6 +47,7 @@ #include "pybuart.h" #include "pybioctl.h" #include "pybsleep.h" +#include "mpcallback.h" #include "mpexception.h" #include "py/mpstate.h" #include "osi.h" @@ -98,6 +99,8 @@ STATIC bool uart_rx_wait (pyb_uart_obj_t *self, uint32_t timeout); STATIC void UARTGenericIntHandler(uint32_t uart_id); STATIC void UART0IntHandler(void); STATIC void UART1IntHandler(void); +STATIC void uart_callback_enable (mp_obj_t self_in); +STATIC void uart_callback_disable (mp_obj_t self_in); /****************************************************************************** DEFINE PRIVATE TYPES @@ -115,13 +118,14 @@ struct _pyb_uart_obj_t { 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) - bool enabled; + byte peripheral; }; /****************************************************************************** DECLARE PRIVATE DATA ******************************************************************************/ STATIC pyb_uart_obj_t pyb_uart_obj[PYB_NUM_UARTS]; +STATIC const mp_cb_methods_t uart_cb_methods; /****************************************************************************** DEFINE PUBLIC FUNCTIONS @@ -175,41 +179,60 @@ 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) { + // 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 { + 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); + + // enable the interrupts now + uart_callback_enable (self); + + return _callback; +} + /****************************************************************************** DEFINE PRIVATE FUNCTIONS ******************************************************************************/ // assumes init parameters have been set up correctly STATIC void uart_init (pyb_uart_obj_t *self) { - uint uartPerh; - - switch (self->uart_id) { - case PYB_UART_0: + if (self->uart_id == PYB_UART_0) { self->reg = UARTA0_BASE; - uartPerh = PRCM_UARTA0; - MAP_UARTIntRegister(UARTA0_BASE, UART0IntHandler); - MAP_IntPrioritySet(INT_UARTA0, INT_PRIORITY_LVL_3); - break; - case PYB_UART_1: + self->peripheral = PRCM_UARTA0; + } + else { self->reg = UARTA1_BASE; - uartPerh = PRCM_UARTA1; - MAP_UARTIntRegister(UARTA1_BASE, UART1IntHandler); - MAP_IntPrioritySet(INT_UARTA1, INT_PRIORITY_LVL_3); - break; - default: - return; + self->peripheral = PRCM_UARTA1; } // Enable the peripheral clock - MAP_PRCMPeripheralClkEnable(uartPerh, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK); + MAP_PRCMPeripheralClkEnable(self->peripheral, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK); // Reset the uart - MAP_PRCMPeripheralReset(uartPerh); + MAP_PRCMPeripheralReset(self->peripheral); // Initialize the UART - MAP_UARTConfigSetExpClk(self->reg, MAP_PRCMPeripheralClockGet(uartPerh), + MAP_UARTConfigSetExpClk(self->reg, MAP_PRCMPeripheralClockGet(self->peripheral), self->baudrate, self->config); - // Enbale the FIFO + // Enable the FIFO MAP_UARTFIFOEnable(self->reg); // Configure the FIFO interrupt levels @@ -217,21 +240,13 @@ STATIC void uart_init (pyb_uart_obj_t *self) { // Configure the flow control mode UARTFlowControlSet(self->reg, self->flowcontrol); - - // Setup the RX interrupts - if (self->read_buf != NULL) { - MAP_UARTIntEnable(self->reg, UART_INT_RX | UART_INT_RT); - } - else { - MAP_UARTIntDisable(self->reg, UART_INT_RX | UART_INT_RT); - } } // Waits at most timeout milliseconds 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) { - for (;;) { + for ( ; ; ) { if (uart_rx_any(self)) { return true; // have at least 1 char ready for reading } @@ -256,8 +271,8 @@ STATIC void UARTGenericIntHandler(uint32_t uart_id) { MAP_UARTIntClear(self->reg, UART_INT_RX | UART_INT_RT); while (UARTCharsAvail(self->reg)) { int data = MAP_UARTCharGetNonBlocking(self->reg); - if (MICROPY_STDIO_UART == self->uart_id && data == user_interrupt_char) { - // raise exception when interrupts are finished + if (pyb_stdio_uart == self && data == user_interrupt_char) { + // raise an exception when interrupts are finished mpexception_keyboard_nlr_jump(); } else if (self->read_buf_len != 0) { @@ -269,6 +284,9 @@ STATIC void UARTGenericIntHandler(uint32_t uart_id) { } } } + // call the user defined handler + mp_obj_t _callback = mpcallback_find(self); + mpcallback_handler(_callback); } } @@ -280,14 +298,23 @@ STATIC void UART1IntHandler(void) { UARTGenericIntHandler(1); } +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); +} + +STATIC void uart_callback_disable (mp_obj_t self_in) { + pyb_uart_obj_t *self = self_in; + MAP_UARTIntDisable(self->reg, UART_INT_RX | UART_INT_RT); +} + /******************************************************************************/ /* Micro Python bindings */ STATIC void pyb_uart_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { pyb_uart_obj_t *self = self_in; - if (!self->enabled) { - print(env, "", self->uart_id); - } else { + if (self->baudrate > 0) { print(env, "", self->uart_id); + } } /// \method init(baudrate, bits=8, parity=None, stop=1, *, timeout=1000, timeout_char=0, read_buf_len=128) @@ -326,9 +356,8 @@ STATIC void pyb_uart_print(void (*print)(void *env, const char *fmt, ...), void /// - `stop` is the number of stop bits, 1 or 2. /// - `flowcontrol` is the flow control mode, `None`, `UART.FLOW_TX`, /// `UART.FLOW_RX', 'UART.FLOW_TXRX`. -/// - `timeout` is the timeout in milliseconds to wait for the first character. -/// - `timeout_char` is the timeout in milliseconds to wait between characters. -/// - `read_buf_len` is the character length of the read buffer (0 to disable). +/// - `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} }, @@ -337,7 +366,6 @@ STATIC const mp_arg_t pyb_uart_init_args[] = { { 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_read_buf_len, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 128} }, }; 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) { @@ -349,21 +377,11 @@ STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, mp_uint_t n_args, con self->timeout = args[5].u_int; self->timeout_char = args[6].u_int; - // setup the read buffer - m_del(byte, self->read_buf, self->read_buf_len); + // no read buffer for the moment self->read_buf_head = 0; self->read_buf_tail = 0; - - if (args[7].u_int <= 0) { - // no read buffer - self->read_buf_len = 0; - self->read_buf = NULL; - } - else { - // read buffer using interrupts - self->read_buf_len = args[7].u_int; - self->read_buf = m_new(byte, args[7].u_int); - } + self->read_buf_len = 0; + self->read_buf = NULL; // get the baudrate self->baudrate = args[0].u_int; @@ -395,7 +413,6 @@ STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, mp_uint_t n_args, con } // Stop bits self->config |= (args[3].u_int == 1 ? UART_CONFIG_STOP_ONE : UART_CONFIG_STOP_TWO); - // Flow control self->flowcontrol = args[4].u_int; } @@ -403,9 +420,9 @@ STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, mp_uint_t n_args, con self->config = UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE; self->flowcontrol = UART_FLOWCONTROL_NONE; } + // initialize and enable the uart uart_init (self); - self->enabled = true; // register it with the sleep module pybsleep_add ((const mp_obj_t)self, (WakeUpCB_t)uart_init); @@ -414,7 +431,7 @@ STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, mp_uint_t n_args, con /// \classmethod \constructor(bus, ...) /// -/// Construct a UART object on the given bus id. `bus id` can be 0-1 +/// Construct a UART object on the given bus id. `bus id` 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). @@ -441,9 +458,6 @@ STATIC mp_obj_t pyb_uart_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t self->base.type = &pyb_uart_type; self->uart_id = uart_id; if (n_args > 1 || n_kw > 0) { - // invalidate the buffer and clear the enabled flag - self->read_buf = NULL; - self->enabled = false; // start the peripheral mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); @@ -462,31 +476,14 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_uart_init_obj, 1, pyb_uart_init); /// Turn off the UART bus. mp_obj_t pyb_uart_deinit(mp_obj_t self_in) { pyb_uart_obj_t *self = self_in; - uint uartPerh; - - switch (self->uart_id) { - - case PYB_UART_0: - uartPerh = PRCM_UARTA0; - break; - - case PYB_UART_1: - uartPerh = PRCM_UARTA1; - break; - - default: - return mp_const_none; - } // unregister it with the sleep module pybsleep_remove (self); - self->enabled = false; + // invalidate the baudrate + self->baudrate = 0; MAP_UARTIntDisable(self->reg, UART_INT_RX | UART_INT_RT); - MAP_UARTIntClear(self->reg, UART_INT_RX | UART_INT_RT); - MAP_UARTIntUnregister(self->reg); MAP_UARTDisable(self->reg); - MAP_PRCMPeripheralClkDisable(uartPerh, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK); - + MAP_PRCMPeripheralClkDisable(self->peripheral, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_deinit_obj, pyb_uart_deinit); @@ -503,6 +500,33 @@ STATIC mp_obj_t pyb_uart_any(mp_obj_t self_in) { } 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_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); + + // check if any parameters were passed + pyb_uart_obj_t *self = pos_args[0]; + mp_obj_t _callback = mpcallback_find((mp_obj_t)self); + if (kw_args->used > 0 || !_callback) { + + // convert the priority to the correct value + uint priority = mpcallback_translate_priority (args[2].u_int); + + // check the power mode + if (PYB_PWR_MODE_ACTIVE != args[3].u_int) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + } + + // register a new callback + return uart_callback_new (self, args[1].u_obj, args[3].u_int, priority); + } + return _callback; +} +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`. @@ -540,6 +564,7 @@ STATIC const mp_map_elem_t pyb_uart_locals_dict_table[] = { { 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_callback), (mp_obj_t)&pyb_uart_callback_obj }, /// \method read([nbytes]) { MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj }, @@ -582,7 +607,7 @@ STATIC mp_uint_t pyb_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, i // read the data byte *orig_buf = buf; - for (;;) { + for ( ; ; ) { *buf++ = uart_rx_char(self); if (--size == 0 || !uart_rx_wait(self, self->timeout_char)) { // return number of bytes read @@ -628,6 +653,12 @@ STATIC const mp_stream_p_t uart_stream_p = { .is_text = false, }; +STATIC const mp_cb_methods_t uart_cb_methods = { + .init = pyb_uart_callback, + .enable = uart_callback_enable, + .disable = uart_callback_disable, +}; + const mp_obj_type_t pyb_uart_type = { { &mp_type_type }, .name = MP_QSTR_UART, diff --git a/cc3200/mods/pybuart.h b/cc3200/mods/pybuart.h index 73eab476e2..2441c1b9dc 100644 --- a/cc3200/mods/pybuart.h +++ b/cc3200/mods/pybuart.h @@ -44,5 +44,6 @@ 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); #endif // PYBUART_H_ diff --git a/cc3200/mptask.c b/cc3200/mptask.c index 05843c3dc5..a3b6bb2894 100644 --- a/cc3200/mptask.c +++ b/cc3200/mptask.c @@ -40,6 +40,7 @@ #include "rom_map.h" #include "pin.h" #include "prcm.h" +#include "interrupt.h" #include "pybuart.h" #include "pybpin.h" #include "pybrtc.h" @@ -134,16 +135,18 @@ soft_reset: // we are alive, so let the world know it mperror_enable_heartbeat(); - // configure stdio uart pins with the correct af + // 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 *)&pin_GPIO1, PIN_MODE_3, 0, PIN_TYPE_STD, PIN_STRENGTH_2MA); pin_config ((pin_obj_t *)&pin_GPIO2, PIN_MODE_3, 0, PIN_TYPE_STD, PIN_STRENGTH_2MA); - // Instantiate the stdio uart + // instantiate the stdio uart 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); pybsleep_reset_cause_t rstcause = pybsleep_get_reset_cause(); if (rstcause < PYB_SLP_SOFT_RESET) { diff --git a/cc3200/qstrdefsport.h b/cc3200/qstrdefsport.h index b4040bf7b3..6b123a6e7c 100644 --- a/cc3200/qstrdefsport.h +++ b/cc3200/qstrdefsport.h @@ -151,7 +151,6 @@ Q(disable) // for RTC class Q(RTC) Q(datetime) -Q(callback) // for time class Q(utime) @@ -245,7 +244,7 @@ Q(handler) Q(intmode) Q(value) Q(priority) -Q(wake) +Q(wakes) // for Sleep class Q(Sleep)