cc3200: New SPI API.

This commit is contained in:
Daniel Campora 2015-09-13 21:44:09 +02:00
parent 624cdeacc4
commit aba75e1233
6 changed files with 403 additions and 252 deletions

View File

@ -43,28 +43,11 @@
#include "pybspi.h"
#include "mpexception.h"
#include "pybsleep.h"
#include "pybpin.h"
#include "pins.h"
/// \moduleref pyb
/// \class SPI - a master-driven serial protocol
///
/// SPI is a serial protocol that is driven by a master. At the physical level
/// there are 3 lines: SCK, MOSI, MISO.
///
/// See usage model of I2C; SPI is very similar. Main difference is
/// parameters to init the SPI bus:
///
/// from pyb import SPI
/// spi = SPI(1, SPI.MASTER, baudrate=2000000, bits=8, polarity=0, phase=0, cs_polarity=SPI.ACTIVE_LOW)
///
/// Only required parameter is the baudrate, in Hz. polarity and phase may be 0 or 1.
/// Bit accepts 8, 16, 32. Chip select values are ACTIVE_LOW and ACTIVE_HIGH
///
/// Additional method for SPI:
///
/// data = spi.send_recv(b'1234') # send 4 bytes and receive 4 bytes
/// buf = bytearray(4)
/// spi.send_recv(b'1234', buf) # send 4 bytes and receive 4 into buf
/// spi.send_recv(buf, buf) # send/recv 4 bytes from/to buf
/******************************************************************************
DEFINE TYPES
@ -73,10 +56,6 @@ typedef struct _pyb_spi_obj_t {
mp_obj_base_t base;
uint baudrate;
uint config;
vstr_t tx_vstr;
vstr_t rx_vstr;
uint tx_index;
uint rx_index;
byte polarity;
byte phase;
byte submode;
@ -86,13 +65,15 @@ typedef struct _pyb_spi_obj_t {
/******************************************************************************
DEFINE CONSTANTS
******************************************************************************/
#define PYBSPI_DEF_BAUDRATE 1000000 // 1MHz
#define PYBSPI_FIRST_BIT_MSB 0
/******************************************************************************
DECLARE PRIVATE DATA
******************************************************************************/
STATIC pyb_spi_obj_t pyb_spi_obj = {.baudrate = 0};
STATIC const mp_obj_t pyb_spi_def_pin[3] = {&pin_GP14, &pin_GP16, &pin_GP30};
/******************************************************************************
DEFINE PRIVATE FUNCTIONS
******************************************************************************/
@ -112,21 +93,19 @@ STATIC void pybspi_init (const pyb_spi_obj_t *self) {
}
STATIC void pybspi_tx (pyb_spi_obj_t *self, const void *data) {
uint32_t txdata = 0xFFFFFFFF;
if (data) {
switch (self->wlen) {
case 1:
txdata = (uint8_t)(*(char *)data);
break;
case 2:
txdata = (uint16_t)(*(uint16_t *)data);
break;
case 4:
txdata = (uint32_t)(*(uint32_t *)data);
break;
default:
return;
}
uint32_t txdata;
switch (self->wlen) {
case 1:
txdata = (uint8_t)(*(char *)data);
break;
case 2:
txdata = (uint16_t)(*(uint16_t *)data);
break;
case 4:
txdata = (uint32_t)(*(uint32_t *)data);
break;
default:
return;
}
MAP_SPIDataPut (GSPI_BASE, txdata);
}
@ -151,11 +130,14 @@ STATIC void pybspi_rx (pyb_spi_obj_t *self, void *data) {
}
}
STATIC void pybspi_transfer (pyb_spi_obj_t *self, const char *txdata, char *rxdata, uint32_t len) {
STATIC void pybspi_transfer (pyb_spi_obj_t *self, const char *txdata, char *rxdata, uint32_t len, uint32_t *txchar) {
if (!self->baudrate) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible));
}
// send and receive the data
MAP_SPICSEnable(GSPI_BASE);
for (int i = 0; i < len / self->wlen; i += self->wlen) {
pybspi_tx(self, txdata ? (const void *)&txdata[i] : NULL);
for (int i = 0; i < len; i += self->wlen) {
pybspi_tx(self, txdata ? (const void *)&txdata[i] : txchar);
pybspi_rx(self, rxdata ? (void *)&rxdata[i] : NULL);
}
MAP_SPICSDisable(GSPI_BASE);
@ -166,40 +148,15 @@ STATIC void pybspi_transfer (pyb_spi_obj_t *self, const char *txdata, char *rxda
/******************************************************************************/
STATIC void pyb_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_spi_obj_t *self = self_in;
if (self->baudrate > 0) {
mp_printf(print, "<SPI1, SPI.MASTER, baudrate=%u, bits=%u, polarity=%u, phase=%u, cs_polarity=%q>",
self->baudrate, (self->wlen * 8), self->polarity, self->phase,
(self->config & SPI_CS_ACTIVELOW) ? MP_QSTR_ACTIVE_LOW : MP_QSTR_ACTIVE_HIGH);
mp_printf(print, "SPI(0, SPI.MASTER, baudrate=%u, bits=%u, polarity=%u, phase=%u, firstbit=SPI.MSB)",
self->baudrate, (self->wlen * 8), self->polarity, self->phase);
} else {
mp_print_str(print, "<SPI1>");
mp_print_str(print, "SPI(0)");
}
}
/// \method init(mode, *, baudrate=1000000, bits=8, polarity=0, phase=0, cs_polarity=SPI.ACTIVE_LOW)
///
/// Initialise the SPI bus with the given parameters:
///
/// - `mode` must be MASTER.
/// - `baudrate` is the SCK clock rate.
/// - `bits` is the transfer width size (8, 16, 32).
/// - `polarity` (0, 1).
/// - `phase` (0, 1).
/// - `cs_polarity` can be ACTIVE_LOW or ACTIVE_HIGH.
static const mp_arg_t pybspi_init_args[] = {
{ MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, },
{ MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = PYBSPI_DEF_BAUDRATE} },
{ MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
{ MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_cs_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = SPI_CS_ACTIVELOW} },
};
STATIC mp_obj_t pyb_spi_init_helper(pyb_spi_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(pybspi_init_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(pybspi_init_args), pybspi_init_args, args);
STATIC mp_obj_t pyb_spi_init_helper(pyb_spi_obj_t *self, mp_arg_val_t *args) {
// verify that mode is master
if (args[0].u_int != SPI_MODE_MASTER) {
goto invalid_args;
@ -227,19 +184,36 @@ STATIC mp_obj_t pyb_spi_init_helper(pyb_spi_obj_t *self, mp_uint_t n_args, const
goto invalid_args;
}
uint cs = args[5].u_int;
if (cs != SPI_CS_ACTIVELOW && cs != SPI_CS_ACTIVEHIGH) {
uint firstbit = args[5].u_int;
if (firstbit != PYBSPI_FIRST_BIT_MSB) {
goto invalid_args;
}
// build the configuration
self->baudrate = args[1].u_int;
self->wlen = args[2].u_int >> 3;
self->config = bits | cs | SPI_SW_CTRL_CS | SPI_4PIN_MODE | SPI_TURBO_OFF;
self->config = bits | SPI_CS_ACTIVELOW | SPI_SW_CTRL_CS | SPI_4PIN_MODE | SPI_TURBO_OFF;
self->polarity = polarity;
self->phase = phase;
self->submode = (polarity << 1) | phase;
// assign the pins
mp_obj_t pins_o = args[6].u_obj;
if (pins_o != mp_const_none) {
mp_obj_t *pins;
mp_uint_t n_pins = 3;
if (pins_o == MP_OBJ_NULL) {
// use the default pins
pins = (mp_obj_t *)pyb_spi_def_pin;
} else {
mp_obj_get_array(pins_o, &n_pins, &pins);
if (n_pins != 3) {
goto invalid_args;
}
}
pin_assign_pins_af (pins, n_pins, PIN_TYPE_STD_PU, PIN_FN_SPI, 0);
}
// init the bus
pybspi_init((const pyb_spi_obj_t *)self);
@ -252,32 +226,43 @@ invalid_args:
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
/// \classmethod \constructor(bus, ...)
///
/// Construct an SPI object with the given baudrate. Bus can only be 1.
/// With no extra parameters, the SPI 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.
/// See `init` for parameters of initialisation.
STATIC mp_obj_t pyb_spi_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_OBJ_FUN_ARGS_MAX, true);
static const mp_arg_t pyb_spi_init_args[] = {
{ MP_QSTR_id, MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_mode, MP_ARG_INT, {.u_int = SPI_MODE_MASTER} },
{ MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1000000} }, // 1MHz
{ MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
{ MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_firstbit, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = PYBSPI_FIRST_BIT_MSB} },
{ MP_QSTR_pins, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
};
STATIC mp_obj_t pyb_spi_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *all_args) {
// parse args
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);
mp_arg_val_t args[MP_ARRAY_SIZE(pyb_spi_init_args)];
mp_arg_parse_all(n_args, all_args, &kw_args, MP_ARRAY_SIZE(args), pyb_spi_init_args, args);
// check the peripheral id
if (args[0].u_int != 0) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
}
// setup the object
pyb_spi_obj_t *self = &pyb_spi_obj;
self->base.type = &pyb_spi_type;
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_spi_init_helper(self, n_args - 1, args + 1, &kw_args);
}
// start the peripheral
pyb_spi_init_helper(self, &args[1]);
return self;
}
STATIC mp_obj_t pyb_spi_init(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
return pyb_spi_init_helper(args[0], n_args - 1, args + 1, kw_args);
STATIC mp_obj_t pyb_spi_init(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_spi_init_args) - 1];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), &pyb_spi_init_args[1], args);
return pyb_spi_init_helper(pos_args[0], args);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_init_obj, 1, pyb_spi_init);
@ -295,152 +280,112 @@ STATIC mp_obj_t pyb_spi_deinit(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_spi_deinit_obj, pyb_spi_deinit);
/// \method send(send, *, timeout=5000)
/// Send data on the bus:
///
/// - `send` is the data to send (a byte to send, or a buffer object).
/// - `timeout` is the timeout in milliseconds to wait for the send.
///
STATIC mp_obj_t pyb_spi_send (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_send, MP_ARG_REQUIRED | MP_ARG_OBJ, },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} },
};
STATIC mp_obj_t pyb_spi_write (mp_obj_t self_in, mp_obj_t buf) {
// parse args
pyb_spi_obj_t *self = pos_args[0];
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
pyb_spi_obj_t *self = self_in;
// get the buffer to send from
mp_buffer_info_t bufinfo;
uint8_t data[1];
pyb_buf_get_for_send(args[0].u_obj, &bufinfo, data);
pyb_buf_get_for_send(buf, &bufinfo, data);
// just send
pybspi_transfer(self, (const char *)bufinfo.buf, NULL, bufinfo.len);
pybspi_transfer(self, (const char *)bufinfo.buf, NULL, bufinfo.len, NULL);
return mp_const_none;
// return the number of bytes written
return mp_obj_new_int(bufinfo.len);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_send_obj, 1, pyb_spi_send);
STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_spi_write_obj, pyb_spi_write);
/// \method recv(recv, *, timeout=5000)
///
/// Receive data on the bus:
///
/// - `recv` can be an integer, which is the number of bytes to receive,
/// or a mutable buffer, which will be filled with received bytes.
/// - `timeout` is the timeout in milliseconds to wait for the receive.
///
/// Return: if `recv` is an integer then a new buffer of the bytes received,
/// otherwise the same buffer that was passed in to `recv`.
STATIC mp_obj_t pyb_spi_recv(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
STATIC mp_obj_t pyb_spi_read(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_recv, MP_ARG_REQUIRED | MP_ARG_OBJ, },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} },
{ MP_QSTR_nbytes, MP_ARG_REQUIRED | MP_ARG_OBJ, },
{ MP_QSTR_write, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0x00} },
};
// parse args
pyb_spi_obj_t *self = pos_args[0];
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), allowed_args, args);
// get the buffer to receive into
vstr_t vstr;
mp_obj_t o_ret = pyb_buf_get_for_recv(args[0].u_obj, &vstr);
pyb_buf_get_for_recv(args[0].u_obj, &vstr);
// just receive
pybspi_transfer(self, NULL, vstr.buf, vstr.len);
uint32_t write = args[1].u_int;
pybspi_transfer(self, NULL, vstr.buf, vstr.len, &write);
// return the received data
if (o_ret != MP_OBJ_NULL) {
return o_ret;
} else {
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_recv_obj, 1, pyb_spi_recv);
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_read_obj, 1, pyb_spi_read);
/// \method send_recv(send, recv=None, *, timeout=5000)
///
/// Send and receive data on the bus at the same time:
///
/// - `send` is the data to send (an integer to send, or a buffer object).
/// - `recv` is a mutable buffer which will be filled with received bytes.
/// It can be the same as `send`, or omitted. If omitted, a new buffer will
/// be created.
/// - `timeout` is the timeout in milliseconds to wait for the transaction to complete.
///
/// Return: the buffer with the received bytes.
STATIC mp_obj_t pyb_spi_send_recv (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
STATIC mp_obj_t pyb_spi_readinto(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_send, MP_ARG_REQUIRED | MP_ARG_OBJ, },
{ MP_QSTR_recv, MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} },
{ MP_QSTR_buf, MP_ARG_REQUIRED | MP_ARG_OBJ, },
{ MP_QSTR_write, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0x00} },
};
// parse args
pyb_spi_obj_t *self = pos_args[0];
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), allowed_args, args);
// get buffers to send from/receive to
mp_buffer_info_t bufinfo_send;
// get the buffer to receive into
vstr_t vstr;
pyb_buf_get_for_recv(args[0].u_obj, &vstr);
// just receive
uint32_t write = args[1].u_int;
pybspi_transfer(self, NULL, vstr.buf, vstr.len, &write);
// return the number of bytes received
return mp_obj_new_int(vstr.len);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_readinto_obj, 1, pyb_spi_readinto);
STATIC mp_obj_t pyb_spi_write_readinto (mp_obj_t self, mp_obj_t writebuf, mp_obj_t readbuf) {
// get buffers to write from/read to
mp_buffer_info_t bufinfo_write;
uint8_t data_send[1];
mp_buffer_info_t bufinfo_recv;
vstr_t vstr_recv;
mp_obj_t o_ret;
mp_buffer_info_t bufinfo_read;
if (args[0].u_obj == args[1].u_obj) {
// same object for sending and receiving, it must be a r/w buffer
mp_get_buffer_raise(args[0].u_obj, &bufinfo_send, MP_BUFFER_RW);
bufinfo_recv = bufinfo_send;
o_ret = args[0].u_obj;
if (writebuf == readbuf) {
// same object for writing and reading, it must be a r/w buffer
mp_get_buffer_raise(writebuf, &bufinfo_write, MP_BUFFER_RW);
bufinfo_read = bufinfo_write;
} else {
// get the buffer to send from
pyb_buf_get_for_send(args[0].u_obj, &bufinfo_send, data_send);
// get the buffer to write from
pyb_buf_get_for_send(writebuf, &bufinfo_write, data_send);
// get the buffer to receive into
if (args[1].u_obj == mp_const_none) {
// only the send was argument given, so create a fresh buffer of the send length
vstr_init_len(&vstr_recv, bufinfo_send.len);
bufinfo_recv.len = vstr_recv.len;
bufinfo_recv.buf = vstr_recv.buf;
o_ret = MP_OBJ_NULL;
} else {
// recv argument given
mp_get_buffer_raise(args[1].u_obj, &bufinfo_recv, MP_BUFFER_WRITE);
if (bufinfo_recv.len != bufinfo_send.len) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
o_ret = args[1].u_obj;
// get the read buffer
mp_get_buffer_raise(readbuf, &bufinfo_read, MP_BUFFER_WRITE);
if (bufinfo_read.len != bufinfo_write.len) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
}
// send and receive
pybspi_transfer(self, (const char *)bufinfo_send.buf, bufinfo_recv.buf, bufinfo_send.len);
pybspi_transfer(self, (const char *)bufinfo_write.buf, bufinfo_read.buf, bufinfo_write.len, NULL);
// return the received data
if (o_ret != MP_OBJ_NULL) {
return o_ret;
} else {
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr_recv);
}
// return the number of transferred bytes
return mp_obj_new_int(bufinfo_write.len);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_send_recv_obj, 1, pyb_spi_send_recv);
STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_spi_write_readinto_obj, pyb_spi_write_readinto);
STATIC const mp_map_elem_t pyb_spi_locals_dict_table[] = {
// instance methods
{ MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pyb_spi_init_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_deinit), (mp_obj_t)&pyb_spi_deinit_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_send), (mp_obj_t)&pyb_spi_send_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&pyb_spi_recv_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_send_recv), (mp_obj_t)&pyb_spi_send_recv_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&pyb_spi_write_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&pyb_spi_read_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_readinto), (mp_obj_t)&pyb_spi_readinto_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_write_readinto), (mp_obj_t)&pyb_spi_write_readinto_obj },
// class constants
{ MP_OBJ_NEW_QSTR(MP_QSTR_MASTER), MP_OBJ_NEW_SMALL_INT(SPI_MODE_MASTER) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ACTIVE_LOW), MP_OBJ_NEW_SMALL_INT(SPI_CS_ACTIVELOW) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ACTIVE_HIGH), MP_OBJ_NEW_SMALL_INT(SPI_CS_ACTIVEHIGH) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_MSB), MP_OBJ_NEW_SMALL_INT(PYBSPI_FIRST_BIT_MSB) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_spi_locals_dict, pyb_spi_locals_dict_table);

View File

@ -454,7 +454,7 @@ STATIC mp_obj_t pyb_uart_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t
mp_arg_parse_all(n_args, all_args, &kw_args, MP_ARRAY_SIZE(args), pyb_uart_init_args, args);
// work out the uart id
uint8_t uart_id;
uint uart_id;
if (args[0].u_obj == mp_const_none) {
if (args[5].u_obj != MP_OBJ_NULL) {
mp_obj_t *pins;
@ -474,7 +474,7 @@ STATIC mp_obj_t pyb_uart_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t
uart_id = mp_obj_get_int(args[0].u_obj);
}
if (uart_id < PYB_UART_0 || uart_id > PYB_UART_1) {
if (uart_id > PYB_UART_1) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
}

View File

@ -339,21 +339,24 @@ Q(RTC_WAKE)
// for SPI class
Q(SPI)
Q(id)
Q(mode)
Q(baudrate)
Q(bits)
Q(polarity)
Q(phase)
Q(cs_polarity)
Q(firstbit)
Q(init)
Q(deinit)
Q(send)
Q(recv)
Q(send_recv)
Q(timeout)
Q(write)
Q(read)
Q(readinto)
Q(write_readinto)
Q(nbytes)
Q(write)
Q(buf)
Q(MASTER)
Q(ACTIVE_LOW)
Q(ACTIVE_HIGH)
Q(MSB)
// for Timer class
Q(Timer)

View File

@ -10,7 +10,7 @@ there are 3 lines: SCK, MOSI, MISO.
See usage model of I2C; SPI is very similar. Main difference is
parameters to init the SPI bus::
from pyb import SPI
spi = SPI(1, SPI.MASTER, baudrate=600000, polarity=1, phase=0, crc=0x7)
@ -19,44 +19,43 @@ there are 3 lines: SCK, MOSI, MISO.
to sample data on the first or second clock edge respectively. Crc can be
None for no CRC, or a polynomial specifier.
Additional methods for SPI::
data = spi.send_recv(b'1234') # send 4 bytes and receive 4 bytes
buf = bytearray(4)
spi.send_recv(b'1234', buf) # send 4 bytes and receive 4 into buf
spi.send_recv(buf, buf) # send/recv 4 bytes from/to buf
.. only:: port_wipy
See usage model of I2C; SPI is very similar. Main difference is
parameters to init the SPI bus::
from pyb import SPI
spi = SPI(1, SPI.MASTER, baudrate=1000000, polarity=0, phase=0, cs_polarity=SPI.ACTIVE_LOW)
spi = SPI(1, SPI.MASTER, baudrate=1000000, polarity=0, phase=0, firstbit=SPI.MSB)
Only required parameter is mode, must be SPI.MASTER. Polarity can be 0 or
1, and is the level the idle clock line sits at. Phase can be 0 or 1 to
sample data on the first or second clock edge respectively.
Additional methods for SPI::
data = spi.send_recv(b'1234') # send 4 bytes and receive 4 bytes
buf = bytearray(4)
spi.send_recv(b'1234', buf) # send 4 bytes and receive 4 into buf
spi.send_recv(buf, buf) # send/recv 4 bytes from/to buf
Constructors
------------
.. only:: port_pyboard
.. class:: pyb.SPI(bus, ...)
Construct an SPI object on the given bus. ``bus`` can be 1 or 2.
With no additional parameters, the SPI 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.
See ``init`` for parameters of initialisation.
The physical pins of the SPI busses are:
- ``SPI(1)`` is on the X position: ``(NSS, SCK, MISO, MOSI) = (X5, X6, X7, X8) = (PA4, PA5, PA6, PA7)``
- ``SPI(2)`` is on the Y position: ``(NSS, SCK, MISO, MOSI) = (Y5, Y6, Y7, Y8) = (PB12, PB13, PB14, PB15)``
At the moment, the NSS pin is not used by the SPI driver and is free
for other use.
@ -76,13 +75,13 @@ Methods
.. method:: spi.deinit()
Turn off the SPI bus.
.. only:: port_pyboard
.. method:: spi.init(mode, baudrate=328125, \*, prescaler, polarity=1, phase=0, bits=8, firstbit=SPI.MSB, ti=False, crc=None)
Initialise the SPI bus with the given parameters:
- ``mode`` must be either ``SPI.MASTER`` or ``SPI.SLAVE``.
- ``baudrate`` is the SCK clock rate (only sensible for a master).
- ``prescaler`` is the prescaler to use to derive SCK from the APB bus frequency;
@ -92,66 +91,87 @@ Methods
respectively.
- ``firstbit`` can be ``SPI.MSB`` or ``SPI.LSB``.
- ``crc`` can be None for no CRC, or a polynomial specifier.
Note that the SPI clock frequency will not always be the requested baudrate.
The hardware only supports baudrates that are the APB bus frequency
(see :meth:`pyb.freq`) divided by a prescaler, which can be 2, 4, 8, 16, 32,
64, 128 or 256. SPI(1) is on AHB2, and SPI(2) is on AHB1. For precise
control over the SPI clock frequency, specify ``prescaler`` instead of
``baudrate``.
Printing the SPI object will show you the computed baudrate and the chosen
prescaler.
.. only:: port_wipy
.. method:: spi.init(mode, baudrate=1000000, \*, polarity=0, phase=0, bits=8, nss=SPI.ACTIVE_LOW)
.. method:: spi.init(mode, baudrate=1000000, \*, polarity=0, phase=0, bits=8, firstbit=SPI.MSB, pins=(CLK, MOSI, MISO))
Initialise the SPI bus with the given parameters:
- ``mode`` must be ``SPI.MASTER``.
- ``baudrate`` is the SCK clock rate.
- ``polarity`` can be 0 or 1, and is the level the idle clock line sits at.
- ``phase`` can be 0 or 1 to sample data on the first or second clock edge
respectively.
- ``bits`` is the width of each transfer, accepted values are 8, 16 and 32.
- ``cs_polarity`` can be ``SPI.ACTIVE_LOW`` or ``SPI.ACTIVE_HIGH``.
- ``firstbit`` can be ``SPI.MSB`` only.
- ``pins`` is an optional tupple with the pins to assign to the SPI bus.
.. method:: spi.write(buf)
Write the data contained in ``buf``.
Returns the number of bytes written.
.. method:: spi.read(nbytes, *, write=0x00)
Read the ``nbytes`` while writing the data specified by ``write``.
Return the number of bytes read.
.. method:: spi.readinto(buf, *, write=0x00)
Read into the buffer specified by ``buf`` while writing the data specified by
``write``.
Return the number of bytes read.
.. method:: spi.write_readinto(write_buf, read_buf)
Write from ``write_buf`` and read into ``read_buf``. Both buffers must have the
same length.
Returns the number of bytes written
.. only:: port_pyboard
.. method:: spi.recv(recv, \*, timeout=5000)
Note that the SPI clock frequency will not always be the requested baudrate.
Printing the SPI object will show you the computed baudrate and the chosen
prescaler.
Receive data on the bus:
.. method:: spi.recv(recv, \*, timeout=5000)
- ``recv`` can be an integer, which is the number of bytes to receive,
or a mutable buffer, which will be filled with received bytes.
- ``timeout`` is the timeout in milliseconds to wait for the receive.
Receive data on the bus:
Return value: if ``recv`` is an integer then a new buffer of the bytes received,
otherwise the same buffer that was passed in to ``recv``.
.. method:: spi.send(send, \*, timeout=5000)
- ``recv`` can be an integer, which is the number of bytes to receive,
or a mutable buffer, which will be filled with received bytes.
- ``timeout`` is the timeout in milliseconds to wait for the receive.
Send data on the bus:
Return value: if ``recv`` is an integer then a new buffer of the bytes received,
otherwise the same buffer that was passed in to ``recv``.
- ``send`` is the data to send (an integer to send, or a buffer object).
- ``timeout`` is the timeout in milliseconds to wait for the send.
.. method:: spi.send(send, \*, timeout=5000)
Return value: ``None``.
Send data on the bus:
.. method:: spi.send_recv(send, recv=None, \*, timeout=5000)
Send and receive data on the bus at the same time:
- ``send`` is the data to send (an integer to send, or a buffer object).
- ``timeout`` is the timeout in milliseconds to wait for the send.
- ``send`` is the data to send (an integer to send, or a buffer object).
- ``recv`` is a mutable buffer which will be filled with received bytes.
It can be the same as ``send``, or omitted. If omitted, a new buffer will
be created.
- ``timeout`` is the timeout in milliseconds to wait for the receive.
Return value: ``None``.
.. method:: spi.send_recv(send, recv=None, \*, timeout=5000)
Send and receive data on the bus at the same time:
- ``send`` is the data to send (an integer to send, or a buffer object).
- ``recv`` is a mutable buffer which will be filled with received bytes.
It can be the same as ``send``, or omitted. If omitted, a new buffer will
be created.
- ``timeout`` is the timeout in milliseconds to wait for the receive.
Return value: the buffer with the received bytes.
Return value: the buffer with the received bytes.
Constants
---------
@ -174,7 +194,6 @@ Constants
for initialising the SPI bus to master
.. data:: SPI.ACTIVE_LOW
.. data:: SPI.ACTIVE_HIGH
selects the polarity of the NSS pin
.. data:: SPI.MSB
set the first bit to be the most significant bit

149
tests/wipy/spi.py Normal file
View File

@ -0,0 +1,149 @@
'''
SPI test for the CC3200 based boards.
'''
from pyb import SPI
from pyb import Pin
import os
import pyb
machine = os.uname().machine
if 'LaunchPad' in machine:
spi_pins = ('GP14', 'GP16', 'GP30')
elif 'WiPy' in machine:
spi_pins = ('GP14', 'GP16', 'GP30')
else:
raise Exception('Board not supported!')
spi = SPI(0, SPI.MASTER, baudrate=2000000, polarity=0, phase=0, firstbit=SPI.MSB, pins=spi_pins)
print(spi)
spi = SPI(baudrate=5000000)
print(spi)
spi = SPI(0, SPI.MASTER, baudrate=200000, bits=16, polarity=0, phase=0)
print(spi)
spi = SPI(0, SPI.MASTER, baudrate=10000000, polarity=0, phase=1)
print(spi)
spi = SPI(0, SPI.MASTER, baudrate=5000000, bits=32, polarity=1, phase=0)
print(spi)
spi = SPI(0, SPI.MASTER, baudrate=10000000, polarity=1, phase=1)
print(spi)
spi.init(baudrate=20000000, polarity=0, phase=0)
print(spi)
spi=SPI()
print(spi)
SPI(mode=SPI.MASTER)
SPI(mode=SPI.MASTER, pins=spi_pins)
SPI(id=0, mode=SPI.MASTER, polarity=0, phase=0, pins=('GP14', 'GP16', 'GP15'))
SPI(0, SPI.MASTER, polarity=0, phase=0, pins=('GP31', 'GP16', 'GP15'))
spi = SPI(0, SPI.MASTER, baudrate=10000000, polarity=0, phase=0, pins=spi_pins)
print(spi.write('123456') == 6)
buffer_r = bytearray(10)
print(spi.readinto(buffer_r) == 10)
print(spi.readinto(buffer_r, write=0x55) == 10)
read = spi.read(10)
print(len(read) == 10)
read = spi.read(10, write=0xFF)
print(len(read) == 10)
buffer_w = bytearray([1, 2, 3, 4, 5, 6, 7, 8, 9, 0])
print(spi.write_readinto(buffer_w, buffer_r) == 10)
print(buffer_w == buffer_r)
# test all polaritiy and phase combinations
spi.init(polarity=1, phase=0, pins=None)
buffer_r = bytearray(10)
spi.write_readinto(buffer_w, buffer_r)
print(buffer_w == buffer_r)
spi.init(polarity=1, phase=1, pins=None)
buffer_r = bytearray(10)
spi.write_readinto(buffer_w, buffer_r)
print(buffer_w == buffer_r)
spi.init(polarity=0, phase=1, pins=None)
buffer_r = bytearray(10)
spi.write_readinto(buffer_w, buffer_r)
print(buffer_w == buffer_r)
# test 16 and 32 bit transfers
buffer_w = bytearray([1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2])
buffer_r = bytearray(12)
spi.init(SPI.MASTER, baudrate=10000000, bits=16, polarity=0, phase=0, pins=None)
print(spi.write_readinto(buffer_w, buffer_r) == 12)
print(buffer_w == buffer_r)
buffer_r = bytearray(12)
spi.init(SPI.MASTER, baudrate=10000000, bits=32, polarity=0, phase=0, pins=None)
print(spi.write_readinto(buffer_w, buffer_r) == 12)
print(buffer_w == buffer_r)
# check for memory leaks...
for i in range (0, 1000):
spi = SPI(0, SPI.MASTER, baudrate=1000000)
# test deinit
spi = SPI(0, SPI.MASTER, baudrate=1000000)
spi.deinit()
print(spi)
spi = SPI(0, SPI.MASTER, baudrate=1000000)
# next ones must fail
try:
spi = SPI(0, 10, baudrate=10000000, polarity=0, phase=0)
except:
print("Exception")
try:
spi = SPI(0, mode=SPI.MASTER, baudrate=10000000, polarity=1, phase=2)
except:
print("Exception")
try:
spi = SPI(1, mode=SPI.MASTER, baudrate=10000000, polarity=1, phase=1)
except:
print("Exception")
try:
spi = SPI(0, mode=SPI.MASTER, baudrate=2000000, polarity=2, phase=0)
except:
print("Exception")
try:
spi = SPI(0, mode=SPI.MASTER, baudrate=2000000, polarity=2, phase=0, firstbit=2)
except:
print("Exception")
try:
spi = SPI(0, mode=SPI.MASTER, baudrate=2000000, polarity=2, phase=0, pins=('GP1', 'GP2'))
except:
print("Exception")
try:
spi = SPI(0, mode=SPI.MASTER, baudrate=2000000, polarity=0, phase=0, bits=9)
except:
print("Exception")
spi.deinit()
try:
spi.read(15)
except Exception:
print("Exception")
try:
spi.spi.readinto(buffer_r)
except Exception:
print("Exception")
try:
spi.spi.write('abc')
except Exception:
print("Exception")
try:
spi.write_readinto(buffer_w, buffer_r)
except Exception:
print("Exception")
# reinitialization must work
spi.init(baudrate=500000)
print(spi)

35
tests/wipy/spi.py.exp Normal file
View File

@ -0,0 +1,35 @@
SPI(0, SPI.MASTER, baudrate=2000000, bits=8, polarity=0, phase=0, firstbit=SPI.MSB)
SPI(0, SPI.MASTER, baudrate=5000000, bits=8, polarity=0, phase=0, firstbit=SPI.MSB)
SPI(0, SPI.MASTER, baudrate=200000, bits=16, polarity=0, phase=0, firstbit=SPI.MSB)
SPI(0, SPI.MASTER, baudrate=10000000, bits=8, polarity=0, phase=1, firstbit=SPI.MSB)
SPI(0, SPI.MASTER, baudrate=5000000, bits=32, polarity=1, phase=0, firstbit=SPI.MSB)
SPI(0, SPI.MASTER, baudrate=10000000, bits=8, polarity=1, phase=1, firstbit=SPI.MSB)
SPI(0, SPI.MASTER, baudrate=20000000, bits=8, polarity=0, phase=0, firstbit=SPI.MSB)
SPI(0, SPI.MASTER, baudrate=1000000, bits=8, polarity=0, phase=0, firstbit=SPI.MSB)
True
True
True
True
True
True
True
True
True
True
True
True
True
True
SPI(0)
Exception
Exception
Exception
Exception
Exception
Exception
Exception
Exception
Exception
Exception
Exception
SPI(0, SPI.MASTER, baudrate=500000, bits=8, polarity=0, phase=0, firstbit=SPI.MSB)