Commit 6b21c3fd authored by danicampora's avatar danicampora
Browse files

cc3200: Refactor UART and I2C object creation.

I2C objects can be freed by the GC and a __del__ method is provided
in order to de-init the peripheral prior to being garbage collected.
UART objects are now added to a local list and this list is now part
of the VM_STATE.
parent 7807da20
......@@ -34,5 +34,5 @@
#define MICROPY_HW_ENABLE_RNG (1)
#define MICROPY_HW_ENABLE_RTC (1)
#define MICROPY_STDIO_UART PYB_UART_1
#define MICROPY_STDIO_UART PYB_UART_0
#define MICROPY_STDIO_UART_BAUD 115200
......@@ -70,10 +70,15 @@ static void hal_EnableSdCard (void);
#endif
/******************************************************************************
DECLARE LOCAL VARIABLES
DECLARE LOCAL DATA
******************************************************************************/
static volatile uint32_t HAL_tickCount;
/******************************************************************************
DECLARE PUBLIC DATA
******************************************************************************/
struct _pyb_uart_obj_t *pyb_stdio_uart;
/******************************************************************************
DECLARE IMPORTED DATA
******************************************************************************/
......@@ -134,8 +139,9 @@ void mp_hal_stdout_tx_str(const char *str) {
}
void mp_hal_stdout_tx_strn(const char *str, uint32_t len) {
if (MP_STATE_PORT(pyb_stdio_uart) != NULL) {
uart_tx_strn(MP_STATE_PORT(pyb_stdio_uart), str, len);
// send stdout to UART
if (pyb_stdio_uart != NULL) {
uart_tx_strn(pyb_stdio_uart, str, len);
}
// and also to telnet
if (telnet_is_active()) {
......@@ -145,8 +151,8 @@ void mp_hal_stdout_tx_strn(const char *str, uint32_t len) {
void mp_hal_stdout_tx_strn_cooked(const char *str, uint32_t len) {
// send stdout to UART
if (MP_STATE_PORT(pyb_stdio_uart) != NULL) {
uart_tx_strn_cooked(MP_STATE_PORT(pyb_stdio_uart), str, len);
if (pyb_stdio_uart != NULL) {
uart_tx_strn_cooked(pyb_stdio_uart, str, len);
}
// and also to telnet
if (telnet_is_active()) {
......@@ -159,8 +165,8 @@ int mp_hal_stdin_rx_chr(void) {
if (telnet_rx_any()) {
return telnet_rx_char();
}
else if (MP_STATE_PORT(pyb_stdio_uart) != NULL && uart_rx_any(MP_STATE_PORT(pyb_stdio_uart))) {
return uart_rx_char(MP_STATE_PORT(pyb_stdio_uart));
else if (pyb_stdio_uart != NULL && uart_rx_any(pyb_stdio_uart)) {
return uart_rx_char(pyb_stdio_uart);
}
HAL_Delay(1);
}
......
......@@ -52,6 +52,11 @@
" isb \n"); \
}
/******************************************************************************
DECLARE PUBLIC DATA
******************************************************************************/
extern struct _pyb_uart_obj_t *pyb_stdio_uart;
/******************************************************************************
DECLARE PUBLIC FUNCTIONS
******************************************************************************/
......
......@@ -243,16 +243,16 @@ MP_DEFINE_CONST_FUN_OBJ_0(pyb_standby_obj, pyb_standby);
/// Get or set the UART object that the REPL is repeated on.
STATIC mp_obj_t pyb_repl_uart(uint n_args, const mp_obj_t *args) {
if (n_args == 0) {
if (MP_STATE_PORT(pyb_stdio_uart) == NULL) {
if (pyb_stdio_uart == NULL) {
return mp_const_none;
} else {
return MP_STATE_PORT(pyb_stdio_uart);
return pyb_stdio_uart;
}
} else {
if (args[0] == mp_const_none) {
MP_STATE_PORT(pyb_stdio_uart) = NULL;
pyb_stdio_uart = NULL;
} else if (mp_obj_get_type(args[0]) == &pyb_uart_type) {
MP_STATE_PORT(pyb_stdio_uart) = args[0];
pyb_stdio_uart = args[0];
} else {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_num_type_invalid_arguments));
}
......
......@@ -56,6 +56,8 @@
/// Usage:
///
/// adc = pyb.ADC(channel) # create an adc object on the given channel (0 to 3)
/// this automatically configures the pin associated to
/// that analog channel.
/// adc.read() # read channel value
///
/// The sample rate is fixed to 62.5KHz and the resolution to 12 bits.
......
......@@ -97,6 +97,15 @@
/// i2c.mem_write('abc', 0x42, 2, timeout=10)
typedef struct _pyb_i2c_obj_t {
mp_obj_base_t base;
int mode;
union {
uint baudrate;
byte slvaddr;
};
} pyb_i2c_obj_t;
/******************************************************************************
DEFINE CONSTANTS
******************************************************************************/
......@@ -117,10 +126,6 @@
/******************************************************************************
DEFINE PUBLIC FUNCTIONS
******************************************************************************/
void i2c_init0(void) {
MP_STATE_PORT(pyb_i2c_obj) = NULL;
}
// only master mode is available for the moment
void i2c_init (uint mode, uint slvaddr, uint baudrate) {
// Enable the I2C Peripheral
......@@ -139,14 +144,6 @@ void i2c_deinit(void) {
/******************************************************************************/
/* Micro Python bindings */
/******************************************************************************/
typedef struct _pyb_i2c_obj_t {
mp_obj_base_t base;
int mode;
union {
uint baudrate;
byte slvaddr;
};
} pyb_i2c_obj_t;
STATIC bool pybI2C_transaction(uint cmd, uint timeout) {
// Clear all interrupts
......@@ -260,11 +257,15 @@ STATIC bool pybI2C_ScanDevice(byte devAddr, uint timeout) {
STATIC void pyb_i2c_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_i2c_obj_t *self = self_in;
print(env, "I2C0");
print(env, "<I2C0");
if (self->mode == PYBI2C_MODE_MASTER) {
print(env, ", I2C.MASTER, baudrate=%u)", self->baudrate);
} else if (self->mode == PYBI2C_MODE_SLAVE) {
print(env, ", I2C.SLAVE, addr=0x%02x)", self->slvaddr);
print(env, ", I2C.MASTER, baudrate=%u>)", self->baudrate);
}
else if (self->mode == PYBI2C_MODE_SLAVE) {
print(env, ", I2C.SLAVE, addr=0x%02x>)", self->slvaddr);
}
else {
print(env, ">");
}
}
......@@ -310,7 +311,7 @@ STATIC mp_obj_t pyb_i2c_init_helper(pyb_i2c_obj_t *self_in, mp_uint_t n_args, co
/// \classmethod \constructor(bus, ...)
///
/// Construct an I2C object on the given bus. `bus` can be 1.
/// Construct an I2C object on the given bus. `bus` can only be 0.
/// With no additional parameters, the I2C 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.
......@@ -320,25 +321,17 @@ STATIC mp_obj_t pyb_i2c_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
// get i2c number
mp_int_t i2c_id = mp_obj_get_int(args[0]) - 1;
mp_int_t i2c_id = mp_obj_get_int(args[0]);
// check i2c number
// check the i2c number
if (i2c_id != 0) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
// setup the object
pyb_i2c_obj_t *self;
if (MP_STATE_PORT(pyb_i2c_obj) == NULL) {
// create a new I2C object
self = m_new_obj(pyb_i2c_obj_t);
self->base.type = &pyb_i2c_type;
self->mode = PYBI2C_MODE_DISABLED;
MP_STATE_PORT(pyb_i2c_obj) = self;
} else {
// reference the existing I2C object
self = MP_STATE_PORT(pyb_i2c_obj);
}
// create and setup the object
pyb_i2c_obj_t *self = m_new_obj(pyb_i2c_obj_t);
self->base.type = &pyb_i2c_type;
self->mode = PYBI2C_MODE_DISABLED;
if (n_args > 1 || n_kw > 0) {
// start the peripheral
......@@ -610,6 +603,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_mem_write_obj, 1, pyb_i2c_mem_write);
STATIC const mp_map_elem_t pyb_i2c_locals_dict_table[] = {
// instance methods
{ MP_OBJ_NEW_QSTR(MP_QSTR___del__), (mp_obj_t)&pyb_i2c_deinit_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pyb_i2c_init_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_deinit), (mp_obj_t)&pyb_i2c_deinit_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_is_ready), (mp_obj_t)&pyb_i2c_is_ready_obj },
......
......@@ -27,6 +27,5 @@
extern const mp_obj_type_t pyb_i2c_type;
void i2c_init0(void);
void i2c_init (uint mode, uint slvaddr, uint baudrate);
void i2c_deinit(void);
......@@ -25,13 +25,11 @@
* THE SOFTWARE.
*/
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <errno.h>
#include <stdint.h>
#include <string.h>
#include "py/mpstate.h"
#include "mpconfig.h"
#include MICROPY_HAL_H
#include "nlr.h"
......@@ -39,6 +37,7 @@
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
#include "py/objlist.h"
#include "stream.h"
#include "inc/hw_types.h"
#include "inc/hw_ints.h"
......@@ -51,6 +50,7 @@
#include "pybuart.h"
#include "pybioctl.h"
#include "mpexception.h"
#include "py/mpstate.h"
#include "osi.h"
/// \moduleref pyb
......@@ -63,7 +63,7 @@
///
/// from pyb import UART
///
/// uart = UART(1, 9600) # init with given baudrate
/// uart = UART(0, 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.
......@@ -86,9 +86,17 @@
///
/// uart.any() # returns True if any characters waiting
/******************************************************************************
DEFINE CONSTANTS
******************************************************************************/
#define PYBUART_TX_WAIT_MS 1
#define PYBUART_TX_MAX_TIMEOUT_MS 5
/******************************************************************************
DECLARE PRIVATE FUNCTIONS
******************************************************************************/
STATIC pyb_uart_obj_t* pyb_uart_add (pyb_uart_id_t uart_id);
STATIC pyb_uart_obj_t* pyb_uart_find (pyb_uart_id_t uart_id);
STATIC void UARTGenericIntHandler(uint32_t uart_id);
STATIC void UART0IntHandler(void);
STATIC void UART1IntHandler(void);
......@@ -100,7 +108,7 @@ STATIC mp_obj_t pyb_uart_deinit(mp_obj_t self_in);
struct _pyb_uart_obj_t {
mp_obj_base_t base;
pyb_uart_t uart_id;
pyb_uart_id_t uart_id;
uint reg;
uint baudrate;
uint config;
......@@ -114,40 +122,35 @@ struct _pyb_uart_obj_t {
bool enabled;
};
#define PYBUART_TX_WAIT_MS 1
#define PYBUART_TX_MAX_TIMEOUT_MS 5
/******************************************************************************
DEFINE PUBLIC FUNCTIONS
******************************************************************************/
void uart_init0 (void) {
for (int i = 0; i < MP_ARRAY_SIZE(MP_STATE_PORT(pyb_uart_obj_all)); i++) {
MP_STATE_PORT(pyb_uart_obj_all)[i] = NULL;
}
mp_obj_list_init(&MP_STATE_PORT(pyb_uart_list), 0);
}
// unregister all interrupt sources
void uart_deinit(void) {
for (int i = 0; i < MP_ARRAY_SIZE(MP_STATE_PORT(pyb_uart_obj_all)); i++) {
pyb_uart_obj_t *self = MP_STATE_PORT(pyb_uart_obj_all)[i];
if (self != NULL) {
for (int i = PYB_UART_0; i < PYB_NUM_UARTS; i++) {
pyb_uart_obj_t *self;
if ((self = pyb_uart_find (i))) {
pyb_uart_deinit(self);
}
}
}
// assumes Init parameters have been set up correctly
// assumes init parameters have been set up correctly
bool uart_init2(pyb_uart_obj_t *self) {
uint uartPerh;
switch (self->uart_id) {
case PYB_UART_1:
case 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_2:
case PYB_UART_1:
self->reg = UARTA1_BASE;
uartPerh = PRCM_UARTA1;
MAP_UARTIntRegister(UARTA1_BASE, UART1IntHandler);
......@@ -258,34 +261,50 @@ void uart_tx_strn_cooked(pyb_uart_obj_t *self, const char *str, uint len) {
/******************************************************************************
DEFINE PRIVATE FUNCTIONS
******************************************************************************/
STATIC pyb_uart_obj_t* pyb_uart_add (pyb_uart_id_t uart_id) {
// create a new uart object
pyb_uart_obj_t *self = m_new_obj(pyb_uart_obj_t);
self->base.type = &pyb_uart_type;
self->uart_id = uart_id;
self->read_buf = NULL;
self->enabled = false;
// add it to the list
mp_obj_list_append(&MP_STATE_PORT(pyb_uart_list), self);
return self;
}
STATIC void UARTGenericIntHandler(uint32_t uart_id) {
pyb_uart_obj_t *self = MP_STATE_PORT(pyb_uart_obj_all)[uart_id];
uint32_t status;
if (self == NULL) {
// UART object has not been set, so we can't do anything, not
// even disable the IRQ. This should never happen.
return;
STATIC pyb_uart_obj_t* pyb_uart_find (pyb_uart_id_t uart_id) {
for (mp_uint_t i = 0; i < MP_STATE_PORT(pyb_uart_list).len; i++) {
pyb_uart_obj_t *self = (pyb_uart_obj_t *)MP_STATE_PORT(pyb_uart_list).items[i];
if (self->uart_id == uart_id) {
return self;
}
}
return NULL;
}
status = MAP_UARTIntStatus(self->reg, true);
STATIC void UARTGenericIntHandler(uint32_t uart_id) {
pyb_uart_obj_t *self;
uint32_t status;
// Receive interrupt
if (status & (UART_INT_RX | UART_INT_RT)) {
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
mpexception_keyboard_nlr_jump();
}
else if (self->read_buf_len != 0) {
uint16_t next_head = (self->read_buf_head + 1) % self->read_buf_len;
if (next_head != self->read_buf_tail) {
// only store data if room in buf
self->read_buf[self->read_buf_head] = data;
self->read_buf_head = next_head;
if ((self = pyb_uart_find(uart_id))) {
status = MAP_UARTIntStatus(self->reg, true);
// receive interrupt
if (status & (UART_INT_RX | UART_INT_RT)) {
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
mpexception_keyboard_nlr_jump();
}
else if (self->read_buf_len != 0) {
uint16_t next_head = (self->read_buf_head + 1) % self->read_buf_len;
if (next_head != self->read_buf_tail) {
// only store data if room in buf
self->read_buf[self->read_buf_head] = data;
self->read_buf_head = next_head;
}
}
}
}
......@@ -433,7 +452,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. `bus` can be 1-2
/// Construct a UART object on the given bus id. `bus id` can be 0-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).
......@@ -448,26 +467,17 @@ STATIC mp_obj_t pyb_uart_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t
// check arguments
mp_arg_check_num(n_args, n_kw, 1, MP_ARRAY_SIZE(pyb_uart_init_args), true);
// work out port
pyb_uart_t uart_id = mp_obj_get_int(args[0]);
// work out the uart id
pyb_uart_id_t uart_id = mp_obj_get_int(args[0]);
if (uart_id < PYB_UART_1 || uart_id > MP_ARRAY_SIZE(MP_STATE_PORT(pyb_uart_obj_all))) {
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));
}
// create object
// search for an object in the list
pyb_uart_obj_t *self;
if (MP_STATE_PORT(pyb_uart_obj_all)[uart_id - 1] == NULL) {
// create a new UART object
self = m_new_obj(pyb_uart_obj_t);
self->base.type = &pyb_uart_type;
self->uart_id = uart_id;
self->read_buf = NULL;
self->enabled = false;
MP_STATE_PORT(pyb_uart_obj_all)[uart_id - 1] = self;
} else {
// reference an existing UART object
self = MP_STATE_PORT(pyb_uart_obj_all)[uart_id - 1];
if (!(self = pyb_uart_find(uart_id))) {
self = pyb_uart_add(uart_id);
}
if (n_args > 1 || n_kw > 0) {
......@@ -493,11 +503,11 @@ STATIC mp_obj_t pyb_uart_deinit(mp_obj_t self_in) {
switch (self->uart_id) {
case PYB_UART_1:
case PYB_UART_0:
uartPerh = PRCM_UARTA0;
break;
case PYB_UART_2:
case PYB_UART_1:
uartPerh = PRCM_UARTA1;
break;
......@@ -562,7 +572,6 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_readchar_obj, pyb_uart_readchar);
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 },
......@@ -582,9 +591,6 @@ STATIC const mp_map_elem_t pyb_uart_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_readchar), (mp_obj_t)&pyb_uart_readchar_obj },
// class constants
{ MP_OBJ_NEW_QSTR(MP_QSTR_UART1), MP_OBJ_NEW_SMALL_INT(PYB_UART_1) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_UART2), MP_OBJ_NEW_SMALL_INT(PYB_UART_2) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_FLOW_NONE), MP_OBJ_NEW_SMALL_INT(UART_FLOWCONTROL_NONE) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_FLOW_TX), MP_OBJ_NEW_SMALL_INT(UART_FLOWCONTROL_TX) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_FLOW_RX), MP_OBJ_NEW_SMALL_INT(UART_FLOWCONTROL_RX) },
......
......@@ -26,10 +26,11 @@
*/
typedef enum {
PYB_UART_NONE = 0,
PYB_UART_1 = 1,
PYB_UART_2 = 2
} pyb_uart_t;
PYB_UART_NONE = -1,
PYB_UART_0 = 0,
PYB_UART_1 = 1,
PYB_NUM_UARTS
} pyb_uart_id_t;
typedef struct _pyb_uart_obj_t pyb_uart_obj_t;
extern const mp_obj_type_t pyb_uart_type;
......
......@@ -121,9 +121,7 @@ extern const struct _mp_obj_module_t mp_module_network;
mp_obj_t mp_const_user_interrupt; \
mp_obj_t pyb_config_main; \
mp_obj_list_t pyb_extint_list; \
struct _pyb_uart_obj_t *pyb_stdio_uart; \
struct _pyb_uart_obj_t *pyb_uart_obj_all[2]; \
struct _pyb_i2c_obj_t *pyb_i2c_obj; \
mp_obj_list_t pyb_uart_list; \
mp_obj_list_t mod_network_nic_list; \
......@@ -134,10 +132,10 @@ extern const struct _mp_obj_module_t mp_module_network;
#define UINT_FMT "%u"
#define INT_FMT "%d"
typedef int32_t mp_int_t; // must be pointer size
typedef unsigned int mp_uint_t; // must be pointer size
typedef void *machine_ptr_t; // must be of pointer size
typedef const void *machine_const_ptr_t; // must be of pointer size
typedef int32_t mp_int_t; // must be pointer size
typedef unsigned int mp_uint_t; // must be pointer size
typedef void *machine_ptr_t; // must be of pointer size
typedef const void *machine_const_ptr_t; // must be of pointer size
typedef long mp_off_t;
#define MICROPY_BEGIN_ATOMIC_SECTION() disable_irq()
......@@ -158,7 +156,7 @@ typedef long mp_off_t;
// We need to provide a declaration/definition of alloca()
#include <alloca.h>
// Include board specific configurations
// Include board specific configuration
#include "mpconfigboard.h"
#define MICROPY_HAL_H "cc3200_hal.h"
......
......@@ -147,7 +147,6 @@ soft_reset:
mpexception_init0();
uart_init0();
pin_init0();
i2c_init0();
// configure stdio uart pins with the correct af
// param 3 ("mode") is DON'T CARE" for AFs others than GPIO
......@@ -158,7 +157,7 @@ soft_reset:
mp_obj_new_int(MICROPY_STDIO_UART),
mp_obj_new_int(MICROPY_STDIO_UART_BAUD),
};
MP_STATE_PORT(pyb_stdio_uart) = pyb_uart_type.make_new((mp_obj_t)&pyb_uart_type, MP_ARRAY_SIZE(args), 0, args);
pyb_stdio_uart = pyb_uart_type.make_new((mp_obj_t)&pyb_uart_type, MP_ARRAY_SIZE(args), 0, args);
readline_init0();
extint_init0();
......
......@@ -114,8 +114,6 @@ Q(IRQ_HIGH_LEVEL)
// for UART class
Q(UART)
Q(UART1)
Q(UART2)
Q(baudrate)
Q(bits)
Q(stop)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment