From 7533700393b4b5d4858e1f5745be4544b2a970cc Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 21 Apr 2014 12:03:09 +0100 Subject: stmhal: Rename USART to UART. It's really a UART because there is no external clock line (and hence no synchronous ability, at least in the implementation of this module). USART should be reserved for a module that has "S"ynchronous capabilities. Also, UART is shorter and easier to type :) --- stmhal/Makefile | 8 +- stmhal/main.c | 14 +- stmhal/modpyb.c | 4 +- stmhal/printf.c | 8 +- stmhal/pybstdio.c | 14 +- stmhal/qstrdefsport.h | 4 +- stmhal/uart.c | 415 +++++++++++++++++++++++++++++++++++++++++++++++++ stmhal/uart.h | 30 ++++ stmhal/usart.c | 417 -------------------------------------------------- stmhal/usart.h | 30 ---- 10 files changed, 471 insertions(+), 473 deletions(-) create mode 100644 stmhal/uart.c create mode 100644 stmhal/uart.h delete mode 100644 stmhal/usart.c delete mode 100644 stmhal/usart.h (limited to 'stmhal') diff --git a/stmhal/Makefile b/stmhal/Makefile index c4c7f7bfc..5ab405e32 100644 --- a/stmhal/Makefile +++ b/stmhal/Makefile @@ -66,7 +66,10 @@ SRC_C = \ led.c \ pin.c \ pin_named_pins.c \ - usart.c \ + bufhelper.c \ + i2c.c \ + spi.c \ + uart.c \ usb.c \ printf.c \ math.c \ @@ -97,9 +100,6 @@ SRC_C = \ servo.c \ dac.c \ adc.c \ - bufhelper.c \ - i2c.c \ - spi.c \ # pybwlan.c \ diff --git a/stmhal/main.c b/stmhal/main.c index bfcee76b6..42aaff4d0 100644 --- a/stmhal/main.c +++ b/stmhal/main.c @@ -20,7 +20,7 @@ #include "pyexec.h" #include "i2c.h" #include "spi.h" -#include "usart.h" +#include "uart.h" #include "timer.h" #include "led.h" #include "pin.h" @@ -267,20 +267,20 @@ soft_reset: // GC init gc_init(&_heap_start, &_heap_end); - // Change #if 0 to #if 1 if you want REPL on USART_6 (or another usart) + // Change #if 0 to #if 1 if you want REPL on UART_6 (or another uart) // as well as on USB VCP #if 0 { mp_obj_t args[2] = { - MP_OBJ_NEW_SMALL_INT(PYB_USART_6), + MP_OBJ_NEW_SMALL_INT(PYB_UART_6), MP_OBJ_NEW_SMALL_INT(115200), }; - pyb_usart_global_debug = pyb_usart_type.make_new((mp_obj_t)&pyb_usart_type, - sizeof(args) / sizeof(args[0]), - 0, args); + pyb_uart_global_debug = pyb_uart_type.make_new((mp_obj_t)&pyb_uart_type, + sizeof(args) / sizeof(args[0]), + 0, args); } #else - pyb_usart_global_debug = NULL; + pyb_uart_global_debug = NULL; #endif // Micro Python init diff --git a/stmhal/modpyb.c b/stmhal/modpyb.c index 6fb5cdd84..18507f9ef 100644 --- a/stmhal/modpyb.c +++ b/stmhal/modpyb.c @@ -20,7 +20,7 @@ #include "rtc.h" #include "i2c.h" #include "spi.h" -#include "usart.h" +#include "uart.h" #include "adc.h" #include "storage.h" #include "sdcard.h" @@ -292,7 +292,7 @@ STATIC const mp_map_elem_t pyb_module_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_LED), (mp_obj_t)&pyb_led_type }, { MP_OBJ_NEW_QSTR(MP_QSTR_I2C), (mp_obj_t)&pyb_i2c_type }, { MP_OBJ_NEW_QSTR(MP_QSTR_SPI), (mp_obj_t)&pyb_spi_type }, - { MP_OBJ_NEW_QSTR(MP_QSTR_USART), (mp_obj_t)&pyb_usart_type }, + { MP_OBJ_NEW_QSTR(MP_QSTR_UART), (mp_obj_t)&pyb_uart_type }, { MP_OBJ_NEW_QSTR(MP_QSTR_ADC), (mp_obj_t)&pyb_adc_type }, { MP_OBJ_NEW_QSTR(MP_QSTR_ADCAll), (mp_obj_t)&pyb_adc_all_type }, diff --git a/stmhal/printf.c b/stmhal/printf.c index ea90f4980..a1e754aed 100644 --- a/stmhal/printf.c +++ b/stmhal/printf.c @@ -12,7 +12,7 @@ #if 0 #include "lcd.h" #endif -#include "usart.h" +#include "uart.h" #include "usb.h" #if MICROPY_ENABLE_FLOAT @@ -170,11 +170,11 @@ int pfenv_printf(const pfenv_t *pfenv, const char *fmt, va_list args) { } void stdout_print_strn(void *data, const char *str, unsigned int len) { - // send stdout to USART, USB CDC VCP, and LCD if nothing else + // send stdout to UART, USB CDC VCP, and LCD if nothing else bool any = false; - if (pyb_usart_global_debug != PYB_USART_NONE) { - usart_tx_strn_cooked(pyb_usart_global_debug, str, len); + if (pyb_uart_global_debug != PYB_UART_NONE) { + uart_tx_strn_cooked(pyb_uart_global_debug, str, len); any = true; } if (usb_vcp_is_enabled()) { diff --git a/stmhal/pybstdio.c b/stmhal/pybstdio.c index baabfd120..7026698a0 100644 --- a/stmhal/pybstdio.c +++ b/stmhal/pybstdio.c @@ -10,11 +10,11 @@ #include "stream.h" #include "pybstdio.h" #include "usb.h" -#include "usart.h" +#include "uart.h" void stdout_tx_str(const char *str) { - if (pyb_usart_global_debug != PYB_USART_NONE) { - usart_tx_str(pyb_usart_global_debug, str); + if (pyb_uart_global_debug != PYB_UART_NONE) { + uart_tx_str(pyb_uart_global_debug, str); } #if defined(USE_HOST_MODE) && MICROPY_HW_HAS_LCD lcd_print_str(str); @@ -23,8 +23,8 @@ void stdout_tx_str(const char *str) { } void stdout_tx_strn(const char *str, uint len) { - if (pyb_usart_global_debug != PYB_USART_NONE) { - usart_tx_strn(pyb_usart_global_debug, str, len); + if (pyb_uart_global_debug != PYB_UART_NONE) { + uart_tx_strn(pyb_uart_global_debug, str, len); } #if defined(USE_HOST_MODE) && MICROPY_HW_HAS_LCD lcd_print_strn(str, len); @@ -45,8 +45,8 @@ int stdin_rx_chr(void) { #endif if (usb_vcp_rx_num() != 0) { return usb_vcp_rx_get(); - } else if (pyb_usart_global_debug != PYB_USART_NONE && usart_rx_any(pyb_usart_global_debug)) { - return usart_rx_char(pyb_usart_global_debug); + } else if (pyb_uart_global_debug != PYB_UART_NONE && uart_rx_any(pyb_uart_global_debug)) { + return uart_rx_char(pyb_uart_global_debug); } __WFI(); } diff --git a/stmhal/qstrdefsport.h b/stmhal/qstrdefsport.h index b7102b726..830514d35 100644 --- a/stmhal/qstrdefsport.h +++ b/stmhal/qstrdefsport.h @@ -79,8 +79,8 @@ Q(off) Q(toggle) Q(intensity) -// for USART class -Q(USART) +// for UART class +Q(UART) Q(baudrate) Q(bits) Q(stop) diff --git a/stmhal/uart.c b/stmhal/uart.c new file mode 100644 index 000000000..1b0d9e1b6 --- /dev/null +++ b/stmhal/uart.c @@ -0,0 +1,415 @@ +#include +#include + +#include "stm32f4xx_hal.h" + +#include "nlr.h" +#include "misc.h" +#include "mpconfig.h" +#include "qstr.h" +#include "obj.h" +#include "runtime.h" +#include "bufhelper.h" +#include "uart.h" + +// Usage model: +// +// See usage model of I2C in i2c.c. UART is very similar. Main difference is +// parameters to init the UART bus: +// +// 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 8 or 9, stop can be 1 or 2, parity can be None, 0 (even), 1 (odd). +// +// Extra method: +// +// uart.any() # returns True if any characters waiting + +struct _pyb_uart_obj_t { + mp_obj_base_t base; + pyb_uart_t uart_id; + bool is_enabled; + UART_HandleTypeDef uart; +}; + +pyb_uart_obj_t *pyb_uart_global_debug = NULL; + +// assumes Init parameters have been set up correctly +bool uart_init2(pyb_uart_obj_t *uart_obj) { + USART_TypeDef *UARTx = NULL; + + uint32_t GPIO_Pin = 0; + uint8_t GPIO_AF_UARTx = 0; + GPIO_TypeDef* GPIO_Port = NULL; + + switch (uart_obj->uart_id) { + // USART1 is on PA9/PA10 (CK on PA8), PB6/PB7 + case PYB_UART_1: + UARTx = USART1; + GPIO_AF_UARTx = GPIO_AF7_USART1; + +#if defined (PYBV4) || defined(PYBV10) + GPIO_Port = GPIOB; + GPIO_Pin = GPIO_PIN_6 | GPIO_PIN_7; +#else + GPIO_Port = GPIOA; + GPIO_Pin = GPIO_PIN_9 | GPIO_PIN_10; +#endif + + __USART1_CLK_ENABLE(); + break; + + // USART2 is on PA2/PA3 (CK on PA4), PD5/PD6 (CK on PD7) + case PYB_UART_2: + UARTx = USART2; + GPIO_AF_UARTx = GPIO_AF7_USART2; + + GPIO_Port = GPIOA; + GPIO_Pin = GPIO_PIN_2 | GPIO_PIN_3; + + __USART2_CLK_ENABLE(); + break; + + // USART3 is on PB10/PB11 (CK on PB12), PC10/PC11 (CK on PC12), PD8/PD9 (CK on PD10) + case PYB_UART_3: + UARTx = USART3; + GPIO_AF_UARTx = GPIO_AF7_USART3; + +#if defined(PYBV3) || defined(PYBV4) | defined(PYBV10) + GPIO_Port = GPIOB; + GPIO_Pin = GPIO_PIN_10 | GPIO_PIN_11; +#else + GPIO_Port = GPIOD; + GPIO_Pin = GPIO_PIN_8 | GPIO_PIN_9; +#endif + __USART3_CLK_ENABLE(); + break; + + // UART4 is on PA0/PA1, PC10/PC11 + case PYB_UART_4: + UARTx = UART4; + GPIO_AF_UARTx = GPIO_AF8_UART4; + + GPIO_Port = GPIOA; + GPIO_Pin = GPIO_PIN_0 | GPIO_PIN_1; + + __UART4_CLK_ENABLE(); + break; + + // USART6 is on PC6/PC7 (CK on PC8) + case PYB_UART_6: + UARTx = USART6; + GPIO_AF_UARTx = GPIO_AF8_USART6; + + GPIO_Port = GPIOC; + GPIO_Pin = GPIO_PIN_6 | GPIO_PIN_7; + + __USART6_CLK_ENABLE(); + break; + + default: + return false; + } + + // init GPIO + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.Pin = GPIO_Pin; + GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; + GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; + GPIO_InitStructure.Pull = GPIO_PULLUP; + GPIO_InitStructure.Alternate = GPIO_AF_UARTx; + HAL_GPIO_Init(GPIO_Port, &GPIO_InitStructure); + + // init UARTx + uart_obj->uart.Instance = UARTx; + HAL_UART_Init(&uart_obj->uart); + + uart_obj->is_enabled = true; + + return true; +} + +bool uart_init(pyb_uart_obj_t *uart_obj, uint32_t baudrate) { + UART_HandleTypeDef *uh = &uart_obj->uart; + memset(uh, 0, sizeof(*uh)); + uh->Init.BaudRate = baudrate; + uh->Init.WordLength = UART_WORDLENGTH_8B; + uh->Init.StopBits = UART_STOPBITS_1; + uh->Init.Parity = UART_PARITY_NONE; + uh->Init.Mode = UART_MODE_TX_RX; + uh->Init.HwFlowCtl = UART_HWCONTROL_NONE; + uh->Init.OverSampling = UART_OVERSAMPLING_16; + return uart_init2(uart_obj); +} + +void uart_deinit(pyb_uart_obj_t *uart_obj) { + uart_obj->is_enabled = false; + UART_HandleTypeDef *uart = &uart_obj->uart; + HAL_UART_DeInit(uart); + if (uart->Instance == USART1) { + __USART1_FORCE_RESET(); + __USART1_RELEASE_RESET(); + __USART1_CLK_DISABLE(); + } else if (uart->Instance == USART2) { + __USART2_FORCE_RESET(); + __USART2_RELEASE_RESET(); + __USART2_CLK_DISABLE(); + } else if (uart->Instance == USART3) { + __USART3_FORCE_RESET(); + __USART3_RELEASE_RESET(); + __USART3_CLK_DISABLE(); + } else if (uart->Instance == UART4) { + __UART4_FORCE_RESET(); + __UART4_RELEASE_RESET(); + __UART4_CLK_DISABLE(); + } else if (uart->Instance == USART6) { + __USART6_FORCE_RESET(); + __USART6_RELEASE_RESET(); + __USART6_CLK_DISABLE(); + } +} + +bool uart_rx_any(pyb_uart_obj_t *uart_obj) { + return __HAL_UART_GET_FLAG(&uart_obj->uart, UART_FLAG_RXNE); +} + +int uart_rx_char(pyb_uart_obj_t *uart_obj) { + uint8_t ch; + if (HAL_UART_Receive(&uart_obj->uart, &ch, 1, 0) != HAL_OK) { + ch = 0; + } + return ch; +} + +void uart_tx_char(pyb_uart_obj_t *uart_obj, int c) { + uint8_t ch = c; + HAL_UART_Transmit(&uart_obj->uart, &ch, 1, 100000); +} + +void uart_tx_str(pyb_uart_obj_t *uart_obj, const char *str) { + HAL_UART_Transmit(&uart_obj->uart, (uint8_t*)str, strlen(str), 100000); +} + +void uart_tx_strn(pyb_uart_obj_t *uart_obj, const char *str, uint len) { + HAL_UART_Transmit(&uart_obj->uart, (uint8_t*)str, len, 100000); +} + +void uart_tx_strn_cooked(pyb_uart_obj_t *uart_obj, const char *str, uint len) { + for (const char *top = str + len; str < top; str++) { + if (*str == '\n') { + uart_tx_char(uart_obj, '\r'); + } + uart_tx_char(uart_obj, *str); + } +} + +/******************************************************************************/ +/* 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->is_enabled) { + print(env, "UART(%lu)", self->uart_id); + } else { + print(env, "UART(%lu, baudrate=%u, bits=%u, stop=%u", + self->uart_id, self->uart.Init.BaudRate, + self->uart.Init.WordLength == UART_WORDLENGTH_8B ? 8 : 9, + self->uart.Init.StopBits == UART_STOPBITS_1 ? 1 : 2); + if (self->uart.Init.Parity == UART_PARITY_NONE) { + print(env, ", parity=None)"); + } else { + print(env, ", parity=%u)", self->uart.Init.Parity == UART_PARITY_EVEN ? 0 : 1); + } + } +} + +STATIC const mp_arg_parse_t pyb_uart_init_accepted_args[] = { + { MP_QSTR_baudrate, MP_ARG_PARSE_REQUIRED | MP_ARG_PARSE_INT, {.u_int = 9600} }, + { MP_QSTR_bits, MP_ARG_PARSE_KW_ONLY | MP_ARG_PARSE_INT, {.u_int = 8} }, + { MP_QSTR_stop, MP_ARG_PARSE_KW_ONLY | MP_ARG_PARSE_INT, {.u_int = 1} }, + { MP_QSTR_parity, MP_ARG_PARSE_KW_ONLY | MP_ARG_PARSE_OBJ, {.u_obj = mp_const_none} }, +}; +#define PYB_UART_INIT_NUM_ARGS (sizeof(pyb_uart_init_accepted_args) / sizeof(pyb_uart_init_accepted_args[0])) + +STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { + // parse args + mp_arg_parse_val_t vals[PYB_UART_INIT_NUM_ARGS]; + mp_arg_parse_all(n_args, args, kw_args, PYB_UART_INIT_NUM_ARGS, pyb_uart_init_accepted_args, vals); + + // set the UART configuration values + memset(&self->uart, 0, sizeof(self->uart)); + UART_InitTypeDef *init = &self->uart.Init; + init->BaudRate = vals[0].u_int; + init->WordLength = vals[1].u_int == 8 ? UART_WORDLENGTH_8B : UART_WORDLENGTH_9B; + switch (vals[2].u_int) { + case 1: init->StopBits = UART_STOPBITS_1; break; + default: init->StopBits = UART_STOPBITS_2; break; + } + if (vals[3].u_obj == mp_const_none) { + init->Parity = UART_PARITY_NONE; + } else { + machine_int_t parity = mp_obj_get_int(vals[3].u_obj); + init->Parity = (parity & 1) ? UART_PARITY_ODD : UART_PARITY_EVEN; + } + init->Mode = UART_MODE_TX_RX; + init->HwFlowCtl = UART_HWCONTROL_NONE; + init->OverSampling = UART_OVERSAMPLING_16; + + // init UART (if it fails, it's because the port doesn't exist) + if (!uart_init2(self)) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "UART port %d does not exist", self->uart_id)); + } + + return mp_const_none; +} + +STATIC mp_obj_t pyb_uart_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) { + // check arguments + mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); + + // create object + pyb_uart_obj_t *o = m_new_obj(pyb_uart_obj_t); + o->base.type = &pyb_uart_type; + + // work out port + o->uart_id = 0; + if (MP_OBJ_IS_STR(args[0])) { + const char *port = mp_obj_str_get_str(args[0]); + if (0) { +#if defined(PYBV10) + } else if (strcmp(port, "XA") == 0) { + o->uart_id = PYB_UART_XA; + } else if (strcmp(port, "XB") == 0) { + o->uart_id = PYB_UART_XB; + } else if (strcmp(port, "YA") == 0) { + o->uart_id = PYB_UART_YA; + } else if (strcmp(port, "YB") == 0) { + o->uart_id = PYB_UART_YB; +#endif + } else { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "UART port %s does not exist", port)); + } + } else { + o->uart_id = mp_obj_get_int(args[0]); + } + + if (n_args > 1 || n_kw > 0) { + // start the peripheral + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); + pyb_uart_init_helper(o, n_args - 1, args + 1, &kw_args); + } + + return o; +} + +STATIC mp_obj_t pyb_uart_init(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { + return pyb_uart_init_helper(args[0], n_args - 1, args + 1, kw_args); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_uart_init_obj, 1, pyb_uart_init); + +STATIC mp_obj_t pyb_uart_deinit(mp_obj_t self_in) { + pyb_uart_obj_t *self = self_in; + uart_deinit(self); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_deinit_obj, pyb_uart_deinit); + +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; + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_any_obj, pyb_uart_any); + +STATIC const mp_arg_parse_t pyb_uart_send_accepted_args[] = { + { MP_QSTR_send, MP_ARG_PARSE_REQUIRED | MP_ARG_PARSE_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_timeout, MP_ARG_PARSE_KW_ONLY | MP_ARG_PARSE_INT, {.u_int = 5000} }, +}; +#define PYB_UART_SEND_NUM_ARGS (sizeof(pyb_uart_send_accepted_args) / sizeof(pyb_uart_send_accepted_args[0])) + +STATIC mp_obj_t pyb_uart_send(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { + // TODO assumes transmission size is 8-bits wide + + pyb_uart_obj_t *self = args[0]; + + // parse args + mp_arg_parse_val_t vals[PYB_UART_SEND_NUM_ARGS]; + mp_arg_parse_all(n_args - 1, args + 1, kw_args, PYB_UART_SEND_NUM_ARGS, pyb_uart_send_accepted_args, vals); + + // get the buffer to send from + mp_buffer_info_t bufinfo; + uint8_t data[1]; + pyb_buf_get_for_send(vals[0].u_obj, &bufinfo, data); + + // send the data + HAL_StatusTypeDef status = HAL_UART_Transmit(&self->uart, bufinfo.buf, bufinfo.len, vals[1].u_int); + + if (status != HAL_OK) { + // TODO really need a HardwareError object, or something + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_Exception, "HAL_UART_Transmit failed with code %d", status)); + } + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_uart_send_obj, 1, pyb_uart_send); + +STATIC const mp_arg_parse_t pyb_uart_recv_accepted_args[] = { + { MP_QSTR_recv, MP_ARG_PARSE_REQUIRED | MP_ARG_PARSE_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_timeout, MP_ARG_PARSE_KW_ONLY | MP_ARG_PARSE_INT, {.u_int = 5000} }, +}; +#define PYB_UART_RECV_NUM_ARGS (sizeof(pyb_uart_recv_accepted_args) / sizeof(pyb_uart_recv_accepted_args[0])) + +STATIC mp_obj_t pyb_uart_recv(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { + // TODO assumes transmission size is 8-bits wide + + pyb_uart_obj_t *self = args[0]; + + // parse args + mp_arg_parse_val_t vals[PYB_UART_RECV_NUM_ARGS]; + mp_arg_parse_all(n_args - 1, args + 1, kw_args, PYB_UART_RECV_NUM_ARGS, pyb_uart_recv_accepted_args, vals); + + // get the buffer to receive into + mp_buffer_info_t bufinfo; + mp_obj_t o_ret = pyb_buf_get_for_recv(vals[0].u_obj, &bufinfo); + + // receive the data + HAL_StatusTypeDef status = HAL_UART_Receive(&self->uart, bufinfo.buf, bufinfo.len, vals[1].u_int); + + if (status != HAL_OK) { + // TODO really need a HardwareError object, or something + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_Exception, "HAL_UART_Receive failed with code %d", status)); + } + + // return the received data + if (o_ret == MP_OBJ_NULL) { + return vals[0].u_obj; + } else { + return mp_obj_str_builder_end(o_ret); + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_uart_recv_obj, 1, pyb_uart_recv); + +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_send), (mp_obj_t)&pyb_uart_send_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&pyb_uart_recv_obj }, +}; + +STATIC MP_DEFINE_CONST_DICT(pyb_uart_locals_dict, pyb_uart_locals_dict_table); + +const mp_obj_type_t pyb_uart_type = { + { &mp_type_type }, + .name = MP_QSTR_UART, + .print = pyb_uart_print, + .make_new = pyb_uart_make_new, + .locals_dict = (mp_obj_t)&pyb_uart_locals_dict, +}; diff --git a/stmhal/uart.h b/stmhal/uart.h new file mode 100644 index 000000000..a66ed33c5 --- /dev/null +++ b/stmhal/uart.h @@ -0,0 +1,30 @@ +typedef enum { + PYB_UART_NONE = 0, + PYB_UART_1 = 1, + PYB_UART_2 = 2, + PYB_UART_3 = 3, + PYB_UART_4 = 4, + PYB_UART_5 = 5, + PYB_UART_6 = 6, + +#if defined(PYBV10) + PYB_UART_XA = 4, // UART4 on X1, X2 = PA0, PA1 + PYB_UART_XB = 1, // USART1 on X9, X10 = PB6, PB7 + PYB_UART_YA = 6, // USART6 on Y1, Y2 = PC6, PC7 + PYB_UART_YB = 3, // USART3 on Y9, Y10 = PB10, PB11 +#endif + +} pyb_uart_t; + +typedef struct _pyb_uart_obj_t pyb_uart_obj_t; + +extern pyb_uart_obj_t *pyb_uart_global_debug; +extern const mp_obj_type_t pyb_uart_type; + +bool uart_init(pyb_uart_obj_t *uart_obj, uint32_t baudrate); +bool uart_rx_any(pyb_uart_obj_t *uart_obj); +int uart_rx_char(pyb_uart_obj_t *uart_obj); +void uart_tx_str(pyb_uart_obj_t *uart_obj, const char *str); +void 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); + diff --git a/stmhal/usart.c b/stmhal/usart.c deleted file mode 100644 index 4e5502aa3..000000000 --- a/stmhal/usart.c +++ /dev/null @@ -1,417 +0,0 @@ -#include -#include - -#include "stm32f4xx_hal.h" - -#include "nlr.h" -#include "misc.h" -#include "mpconfig.h" -#include "qstr.h" -#include "obj.h" -#include "runtime.h" -#include "bufhelper.h" -#include "usart.h" - -// Usage model: -// -// See usage model of I2C in i2c.c. USART is very similar. Main difference is -// parameters to init the USART bus: -// -// from pyb import USART -// usart = USART(1, 9600) # init with given baudrate -// usart.init(9600, bits=8, stop=1, parity=None) # init with given parameters -// -// Bits can be 8 or 9, stop can be 1 or 2, parity can be None, 0 (even), 1 (odd). -// -// Extra method: -// -// usart.any() # returns True if any characters waiting - -struct _pyb_usart_obj_t { - mp_obj_base_t base; - pyb_usart_t usart_id; - bool is_enabled; - UART_HandleTypeDef uart; -}; - -pyb_usart_obj_t *pyb_usart_global_debug = NULL; - -// assumes Init parameters have been set up correctly -bool usart_init2(pyb_usart_obj_t *usart_obj) { - USART_TypeDef *USARTx = NULL; - - uint32_t GPIO_Pin = 0; - uint8_t GPIO_AF_USARTx = 0; - GPIO_TypeDef* GPIO_Port = NULL; - - switch (usart_obj->usart_id) { - // USART1 is on PA9/PA10, PB6/PB7 - case PYB_USART_1: - USARTx = USART1; - GPIO_AF_USARTx = GPIO_AF7_USART1; - -#if defined(PYBV10) - GPIO_Port = GPIOB; - GPIO_Pin = GPIO_PIN_6 | GPIO_PIN_7; -#else - GPIO_Port = GPIOA; - GPIO_Pin = GPIO_PIN_9 | GPIO_PIN_10; -#endif - - __USART1_CLK_ENABLE(); - break; - -#if !defined(PYBV10) - // USART2 is on PA2/PA3, PD5/PD6 - case PYB_USART_2: - USARTx = USART2; - GPIO_AF_USARTx = GPIO_AF7_USART2; - - GPIO_Port = GPIOD; - GPIO_Pin = GPIO_PIN_5 | GPIO_PIN_6; - - __USART2_CLK_ENABLE(); - break; -#endif - - // USART3 is on PB10/PB11, PC10/PC11, PD8/PD9 - case PYB_USART_3: - USARTx = USART3; - GPIO_AF_USARTx = GPIO_AF7_USART3; - -#if defined(PYBV3) || defined(PYBV4) | defined(PYBV10) - GPIO_Port = GPIOB; - GPIO_Pin = GPIO_PIN_10 | GPIO_PIN_11; -#else - GPIO_Port = GPIOD; - GPIO_Pin = GPIO_PIN_8 | GPIO_PIN_9; -#endif - __USART3_CLK_ENABLE(); - break; - - // UART4 is on PA0/PA1, PC10/PC11 - case PYB_USART_4: - USARTx = UART4; - GPIO_AF_USARTx = GPIO_AF8_UART4; - - GPIO_Port = GPIOA; - GPIO_Pin = GPIO_PIN_0 | GPIO_PIN_1; - - __UART4_CLK_ENABLE(); - break; - - // USART6 is on PC6/PC7 - case PYB_USART_6: - USARTx = USART6; - GPIO_AF_USARTx = GPIO_AF8_USART6; - - GPIO_Port = GPIOC; - GPIO_Pin = GPIO_PIN_6 | GPIO_PIN_7; - - __USART6_CLK_ENABLE(); - break; - - default: - return false; - } - - // init GPIO - GPIO_InitTypeDef GPIO_InitStructure; - GPIO_InitStructure.Pin = GPIO_Pin; - GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; - GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; - GPIO_InitStructure.Pull = GPIO_PULLUP; - GPIO_InitStructure.Alternate = GPIO_AF_USARTx; - HAL_GPIO_Init(GPIO_Port, &GPIO_InitStructure); - - // init USARTx - usart_obj->uart.Instance = USARTx; - HAL_UART_Init(&usart_obj->uart); - - usart_obj->is_enabled = true; - - return true; -} - -bool usart_init(pyb_usart_obj_t *usart_obj, uint32_t baudrate) { - UART_HandleTypeDef *uh = &usart_obj->uart; - memset(uh, 0, sizeof(*uh)); - uh->Init.BaudRate = baudrate; - uh->Init.WordLength = UART_WORDLENGTH_8B; - uh->Init.StopBits = UART_STOPBITS_1; - uh->Init.Parity = UART_PARITY_NONE; - uh->Init.Mode = UART_MODE_TX_RX; - uh->Init.HwFlowCtl = UART_HWCONTROL_NONE; - uh->Init.OverSampling = UART_OVERSAMPLING_16; - return usart_init2(usart_obj); -} - -void usart_deinit(pyb_usart_obj_t *usart_obj) { - usart_obj->is_enabled = false; - UART_HandleTypeDef *uart = &usart_obj->uart; - HAL_UART_DeInit(uart); - if (uart->Instance == USART1) { - __USART1_FORCE_RESET(); - __USART1_RELEASE_RESET(); - __USART1_CLK_DISABLE(); - } else if (uart->Instance == USART2) { - __USART2_FORCE_RESET(); - __USART2_RELEASE_RESET(); - __USART2_CLK_DISABLE(); - } else if (uart->Instance == USART3) { - __USART3_FORCE_RESET(); - __USART3_RELEASE_RESET(); - __USART3_CLK_DISABLE(); - } else if (uart->Instance == UART4) { - __UART4_FORCE_RESET(); - __UART4_RELEASE_RESET(); - __UART4_CLK_DISABLE(); - } else if (uart->Instance == USART6) { - __USART6_FORCE_RESET(); - __USART6_RELEASE_RESET(); - __USART6_CLK_DISABLE(); - } -} - -bool usart_rx_any(pyb_usart_obj_t *usart_obj) { - return __HAL_UART_GET_FLAG(&usart_obj->uart, UART_FLAG_RXNE); -} - -int usart_rx_char(pyb_usart_obj_t *usart_obj) { - uint8_t ch; - if (HAL_UART_Receive(&usart_obj->uart, &ch, 1, 0) != HAL_OK) { - ch = 0; - } - return ch; -} - -void usart_tx_char(pyb_usart_obj_t *usart_obj, int c) { - uint8_t ch = c; - HAL_UART_Transmit(&usart_obj->uart, &ch, 1, 100000); -} - -void usart_tx_str(pyb_usart_obj_t *usart_obj, const char *str) { - HAL_UART_Transmit(&usart_obj->uart, (uint8_t*)str, strlen(str), 100000); -} - -void usart_tx_strn(pyb_usart_obj_t *usart_obj, const char *str, uint len) { - HAL_UART_Transmit(&usart_obj->uart, (uint8_t*)str, len, 100000); -} - -void usart_tx_strn_cooked(pyb_usart_obj_t *usart_obj, const char *str, uint len) { - for (const char *top = str + len; str < top; str++) { - if (*str == '\n') { - usart_tx_char(usart_obj, '\r'); - } - usart_tx_char(usart_obj, *str); - } -} - -/******************************************************************************/ -/* Micro Python bindings */ - -STATIC void pyb_usart_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { - pyb_usart_obj_t *self = self_in; - if (!self->is_enabled) { - print(env, "USART(%lu)", self->usart_id); - } else { - print(env, "USART(%lu, baudrate=%u, bits=%u, stop=%u", - self->usart_id, self->uart.Init.BaudRate, - self->uart.Init.WordLength == UART_WORDLENGTH_8B ? 8 : 9, - self->uart.Init.StopBits == UART_STOPBITS_1 ? 1 : 2); - if (self->uart.Init.Parity == UART_PARITY_NONE) { - print(env, ", parity=None)"); - } else { - print(env, ", parity=%u)", self->uart.Init.Parity == UART_PARITY_EVEN ? 0 : 1); - } - } -} - -STATIC const mp_arg_parse_t pyb_usart_init_accepted_args[] = { - { MP_QSTR_baudrate, MP_ARG_PARSE_REQUIRED | MP_ARG_PARSE_INT, {.u_int = 9600} }, - { MP_QSTR_bits, MP_ARG_PARSE_KW_ONLY | MP_ARG_PARSE_INT, {.u_int = 8} }, - { MP_QSTR_stop, MP_ARG_PARSE_KW_ONLY | MP_ARG_PARSE_INT, {.u_int = 1} }, - { MP_QSTR_parity, MP_ARG_PARSE_KW_ONLY | MP_ARG_PARSE_OBJ, {.u_obj = mp_const_none} }, -}; -#define PYB_USART_INIT_NUM_ARGS (sizeof(pyb_usart_init_accepted_args) / sizeof(pyb_usart_init_accepted_args[0])) - -STATIC mp_obj_t pyb_usart_init_helper(pyb_usart_obj_t *self, uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { - // parse args - mp_arg_parse_val_t vals[PYB_USART_INIT_NUM_ARGS]; - mp_arg_parse_all(n_args, args, kw_args, PYB_USART_INIT_NUM_ARGS, pyb_usart_init_accepted_args, vals); - - // set the USART configuration values - memset(&self->uart, 0, sizeof(self->uart)); - UART_InitTypeDef *init = &self->uart.Init; - init->BaudRate = vals[0].u_int; - init->WordLength = vals[1].u_int == 8 ? UART_WORDLENGTH_8B : UART_WORDLENGTH_9B; - switch (vals[2].u_int) { - case 1: init->StopBits = UART_STOPBITS_1; break; - default: init->StopBits = UART_STOPBITS_2; break; - } - if (vals[3].u_obj == mp_const_none) { - init->Parity = UART_PARITY_NONE; - } else { - machine_int_t parity = mp_obj_get_int(vals[3].u_obj); - init->Parity = (parity & 1) ? UART_PARITY_ODD : UART_PARITY_EVEN; - } - init->Mode = UART_MODE_TX_RX; - init->HwFlowCtl = UART_HWCONTROL_NONE; - init->OverSampling = UART_OVERSAMPLING_16; - - // init USART (if it fails, it's because the port doesn't exist) - if (!usart_init2(self)) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "USART port %d does not exist", self->usart_id)); - } - - return mp_const_none; -} - -STATIC mp_obj_t pyb_usart_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) { - // check arguments - mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); - - // create object - pyb_usart_obj_t *o = m_new_obj(pyb_usart_obj_t); - o->base.type = &pyb_usart_type; - - // work out port - o->usart_id = 0; - if (MP_OBJ_IS_STR(args[0])) { - const char *port = mp_obj_str_get_str(args[0]); - if (0) { -#if defined(PYBV10) - } else if (strcmp(port, "XA") == 0) { - o->usart_id = PYB_USART_XA; - } else if (strcmp(port, "XB") == 0) { - o->usart_id = PYB_USART_XB; - } else if (strcmp(port, "YA") == 0) { - o->usart_id = PYB_USART_YA; - } else if (strcmp(port, "YB") == 0) { - o->usart_id = PYB_USART_YB; -#endif - } else { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "USART port %s does not exist", port)); - } - } else { - o->usart_id = mp_obj_get_int(args[0]); - } - - if (n_args > 1 || n_kw > 0) { - // start the peripheral - mp_map_t kw_args; - mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); - pyb_usart_init_helper(o, n_args - 1, args + 1, &kw_args); - } - - return o; -} - -STATIC mp_obj_t pyb_usart_init(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { - return pyb_usart_init_helper(args[0], n_args - 1, args + 1, kw_args); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_usart_init_obj, 1, pyb_usart_init); - -STATIC mp_obj_t pyb_usart_deinit(mp_obj_t self_in) { - pyb_usart_obj_t *self = self_in; - usart_deinit(self); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_usart_deinit_obj, pyb_usart_deinit); - -STATIC mp_obj_t pyb_usart_any(mp_obj_t self_in) { - pyb_usart_obj_t *self = self_in; - if (usart_rx_any(self)) { - return mp_const_true; - } else { - return mp_const_false; - } -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_usart_any_obj, pyb_usart_any); - -STATIC const mp_arg_parse_t pyb_usart_send_accepted_args[] = { - { MP_QSTR_send, MP_ARG_PARSE_REQUIRED | MP_ARG_PARSE_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_timeout, MP_ARG_PARSE_KW_ONLY | MP_ARG_PARSE_INT, {.u_int = 5000} }, -}; -#define PYB_USART_SEND_NUM_ARGS (sizeof(pyb_usart_send_accepted_args) / sizeof(pyb_usart_send_accepted_args[0])) - -STATIC mp_obj_t pyb_usart_send(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { - // TODO assumes transmission size is 8-bits wide - - pyb_usart_obj_t *self = args[0]; - - // parse args - mp_arg_parse_val_t vals[PYB_USART_SEND_NUM_ARGS]; - mp_arg_parse_all(n_args - 1, args + 1, kw_args, PYB_USART_SEND_NUM_ARGS, pyb_usart_send_accepted_args, vals); - - // get the buffer to send from - mp_buffer_info_t bufinfo; - uint8_t data[1]; - pyb_buf_get_for_send(vals[0].u_obj, &bufinfo, data); - - // send the data - HAL_StatusTypeDef status = HAL_UART_Transmit(&self->uart, bufinfo.buf, bufinfo.len, vals[1].u_int); - - if (status != HAL_OK) { - // TODO really need a HardwareError object, or something - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_Exception, "HAL_UART_Transmit failed with code %d", status)); - } - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_usart_send_obj, 1, pyb_usart_send); - -STATIC const mp_arg_parse_t pyb_usart_recv_accepted_args[] = { - { MP_QSTR_recv, MP_ARG_PARSE_REQUIRED | MP_ARG_PARSE_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_timeout, MP_ARG_PARSE_KW_ONLY | MP_ARG_PARSE_INT, {.u_int = 5000} }, -}; -#define PYB_USART_RECV_NUM_ARGS (sizeof(pyb_usart_recv_accepted_args) / sizeof(pyb_usart_recv_accepted_args[0])) - -STATIC mp_obj_t pyb_usart_recv(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { - // TODO assumes transmission size is 8-bits wide - - pyb_usart_obj_t *self = args[0]; - - // parse args - mp_arg_parse_val_t vals[PYB_USART_RECV_NUM_ARGS]; - mp_arg_parse_all(n_args - 1, args + 1, kw_args, PYB_USART_RECV_NUM_ARGS, pyb_usart_recv_accepted_args, vals); - - // get the buffer to receive into - mp_buffer_info_t bufinfo; - mp_obj_t o_ret = pyb_buf_get_for_recv(vals[0].u_obj, &bufinfo); - - // receive the data - HAL_StatusTypeDef status = HAL_UART_Receive(&self->uart, bufinfo.buf, bufinfo.len, vals[1].u_int); - - if (status != HAL_OK) { - // TODO really need a HardwareError object, or something - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_Exception, "HAL_UART_Receive failed with code %d", status)); - } - - // return the received data - if (o_ret == MP_OBJ_NULL) { - return vals[0].u_obj; - } else { - return mp_obj_str_builder_end(o_ret); - } -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_usart_recv_obj, 1, pyb_usart_recv); - -STATIC const mp_map_elem_t pyb_usart_locals_dict_table[] = { - // instance methods - { MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pyb_usart_init_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_deinit), (mp_obj_t)&pyb_usart_deinit_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_any), (mp_obj_t)&pyb_usart_any_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_send), (mp_obj_t)&pyb_usart_send_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&pyb_usart_recv_obj }, -}; - -STATIC MP_DEFINE_CONST_DICT(pyb_usart_locals_dict, pyb_usart_locals_dict_table); - -const mp_obj_type_t pyb_usart_type = { - { &mp_type_type }, - .name = MP_QSTR_USART, - .print = pyb_usart_print, - .make_new = pyb_usart_make_new, - .locals_dict = (mp_obj_t)&pyb_usart_locals_dict, -}; diff --git a/stmhal/usart.h b/stmhal/usart.h deleted file mode 100644 index e7db1db3d..000000000 --- a/stmhal/usart.h +++ /dev/null @@ -1,30 +0,0 @@ -typedef enum { - PYB_USART_NONE = 0, - PYB_USART_1 = 1, - PYB_USART_2 = 2, - PYB_USART_3 = 3, - PYB_USART_4 = 4, - PYB_USART_5 = 5, - PYB_USART_6 = 6, - -#if defined(PYBV10) - PYB_USART_XA = 4, // USART4 on X1, X2 = PA0, PA1 - PYB_USART_XB = 1, // USART1 on X9, X10 = PB6, PB7 - PYB_USART_YA = 6, // USART6 on Y1, Y2 = PC6, PC7 - PYB_USART_YB = 3, // USART3 on Y9, Y10 = PB10, PB11 -#endif - -} pyb_usart_t; - -typedef struct _pyb_usart_obj_t pyb_usart_obj_t; - -extern pyb_usart_obj_t *pyb_usart_global_debug; -extern const mp_obj_type_t pyb_usart_type; - -bool usart_init(pyb_usart_obj_t *usart_obj, uint32_t baudrate); -bool usart_rx_any(pyb_usart_obj_t *usart_obj); -int usart_rx_char(pyb_usart_obj_t *usart_obj); -void usart_tx_str(pyb_usart_obj_t *usart_obj, const char *str); -void usart_tx_strn(pyb_usart_obj_t *usart_obj, const char *str, uint len); -void usart_tx_strn_cooked(pyb_usart_obj_t *usart_obj, const char *str, uint len); - -- cgit v1.2.3