cc3200: Add I2C module. Only master mode is currently supported.

This commit is contained in:
danicampora 2015-02-10 13:11:27 +01:00
parent 601c814603
commit 99f3f6b5de
16 changed files with 761 additions and 46 deletions

View File

@ -18,6 +18,7 @@ APP_INC += -Iutil
APP_INC += -Ibootmgr
APP_INC += -I$(PY_SRC)
APP_INC += -I$(BUILD)
APP_INC += -I$(BUILD)/genhdr
APP_INC += -I../lib/fatfs
APP_INC += -I../lib/mp-readline
APP_INC += -I../stmhal
@ -89,6 +90,7 @@ APP_MODS_SRC_C = $(addprefix mods/,\
modutime.c \
modwlan.c \
pybextint.c \
pybi2c.c \
pybpin.c \
pybrtc.c \
pybsystick.c \

View File

@ -112,7 +112,7 @@ DRESULT sflash_disk_read(BYTE *buff, DWORD sector, UINT count) {
return STA_NOINIT;
}
if (sector + count > SFLASH_SECTOR_COUNT || count == 0) {
if ((sector + count > SFLASH_SECTOR_COUNT) || (count == 0)) {
return RES_PARERR;
}
@ -145,7 +145,8 @@ DRESULT sflash_disk_write(const BYTE *buff, DWORD sector, UINT count) {
return STA_NOINIT;
}
if (sector + count > SFLASH_SECTOR_COUNT || count == 0) {
if ((sector + count > SFLASH_SECTOR_COUNT) || (count == 0)) {
sflash_disk_flush();
return RES_PARERR;
}

View File

@ -169,10 +169,8 @@ _I2CIntNumberGet(uint32_t ui32Base)
//
//*****************************************************************************
void
I2CMasterInitExpClk(uint32_t ui32Base, uint32_t ui32I2CClk,
bool bFast)
I2CMasterInitExpClk(uint32_t ui32Base, uint32_t ui32SCLFreq)
{
uint32_t ui32SCLFreq;
uint32_t ui32TPR;
//
@ -185,25 +183,13 @@ I2CMasterInitExpClk(uint32_t ui32Base, uint32_t ui32I2CClk,
//
I2CMasterEnable(ui32Base);
//
// Get the desired SCL speed.
//
if(bFast == true)
{
ui32SCLFreq = 400000;
}
else
{
ui32SCLFreq = 100000;
}
//
// Compute the clock divider that achieves the fastest speed less than or
// equal to the desired speed. The numerator is biased to favor a larger
// clock divider so that the resulting clock is always less than or equal
// to the desired clock, never greater.
//
ui32TPR = ((ui32I2CClk + (2 * 10 * ui32SCLFreq) - 1) /
ui32TPR = ((80000000 + (2 * 10 * ui32SCLFreq) - 1) /
(2 * 10 * ui32SCLFreq)) - 1;
HWREG(ui32Base + I2C_O_MTPR) = ui32TPR;
@ -213,7 +199,7 @@ I2CMasterInitExpClk(uint32_t ui32Base, uint32_t ui32I2CClk,
//
if(HWREG(ui32Base + I2C_O_PP) & I2C_PP_HS)
{
ui32TPR = ((ui32I2CClk + (2 * 3 * 3400000) - 1) /
ui32TPR = ((80000000 + (2 * 3 * 3400000) - 1) /
(2 * 3 * 3400000)) - 1;
HWREG(ui32Base + I2C_O_MTPR) = I2C_MTPR_HS | ui32TPR;
}

View File

@ -309,8 +309,7 @@ extern void I2CMasterDataPut(uint32_t ui32Base, uint8_t ui8Data);
extern void I2CMasterDisable(uint32_t ui32Base);
extern void I2CMasterEnable(uint32_t ui32Base);
extern uint32_t I2CMasterErr(uint32_t ui32Base);
extern void I2CMasterInitExpClk(uint32_t ui32Base, uint32_t ui32I2CClk,
bool bFast);
extern void I2CMasterInitExpClk(uint32_t ui32Base, uint32_t ui32SCLFreq);
extern void I2CMasterIntClear(uint32_t ui32Base);
extern void I2CMasterIntDisable(uint32_t ui32Base);
extern void I2CMasterIntEnable(uint32_t ui32Base);

View File

@ -84,4 +84,5 @@
#undef ROM_SPIConfigSetExpClk
#undef ROM_GPIODirModeGet
#undef ROM_GPIOIntTypeGet
#undef ROM_I2CMasterInitExpClk

View File

@ -60,3 +60,13 @@ const pin_obj_t *pin_find_named_pin(const mp_obj_dict_t *named_pins, mp_obj_t na
}
return NULL;
}
const pin_obj_t *pin_find_pin(const mp_obj_dict_t *named_pins, uint pin_num) {
mp_map_t *named_map = mp_obj_dict_get_map((mp_obj_t)named_pins);
for (uint i = 0; i < named_map->used; i++) {
if (((pin_obj_t *)named_map->table[i].value)->pin_num == pin_num) {
return named_map->table[i].value;
}
}
return NULL;
}

View File

@ -62,6 +62,8 @@
#include "mpexception.h"
#include "random.h"
#include "pybextint.h"
#include "pybi2c.h"
#include "utils.h"
#ifdef DEBUG
@ -218,10 +220,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_delay_obj, pyb_delay);
STATIC mp_obj_t pyb_udelay(mp_obj_t usec_in) {
mp_int_t usec = mp_obj_get_int(usec_in);
if (usec > 0) {
uint32_t count = 0;
const uint32_t utime = ((HAL_FCPU_HZ / 1000000) * (usec / 4));
while (++count <= utime) {
}
UtilsDelay(UTILS_DELAY_US_TO_COUNT(usec));
}
return mp_const_none;
}
@ -261,6 +260,17 @@ STATIC mp_obj_t pyb_repl_uart(uint n_args, const mp_obj_t *args) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_repl_uart_obj, 0, 1, pyb_repl_uart);
/// \function mkdisk('path')
/// Formats the selected drive, useful when the filesystem has been damaged beyond repair
STATIC mp_obj_t pyb_mkdisk(mp_obj_t path_o) {
const char *path = mp_obj_str_get_str(path_o);
if (FR_OK != f_mkfs(path, 1, 0)) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_mkdisk_obj, pyb_mkdisk);
MP_DECLARE_CONST_FUN_OBJ(pyb_main_obj); // defined in main.c
STATIC const mp_map_elem_t pyb_module_globals_table[] = {
@ -291,8 +301,7 @@ STATIC const mp_map_elem_t pyb_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_delay), (mp_obj_t)&pyb_delay_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_udelay), (mp_obj_t)&pyb_udelay_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_sync), (mp_obj_t)&pyb_sync_obj },
//{ MP_OBJ_NEW_QSTR(MP_QSTR_Timer), (mp_obj_t)&pyb_timer_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_mkdisk), (mp_obj_t)&pyb_mkdisk_obj },
#if MICROPY_HW_ENABLE_RNG
{ MP_OBJ_NEW_QSTR(MP_QSTR_rng), (mp_obj_t)&pyb_rng_get_obj },
@ -304,7 +313,7 @@ STATIC const mp_map_elem_t pyb_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_Pin), (mp_obj_t)&pin_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ExtInt), (mp_obj_t)&extint_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_I2C), (mp_obj_t)&pyb_i2c_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_UART), (mp_obj_t)&pyb_uart_type },
};

View File

@ -283,7 +283,7 @@ extint_obj_t* extint_register(mp_obj_t pin_obj, uint32_t intmode, uint32_t pull,
intmode != GPIO_BOTH_EDGES &&
intmode != GPIO_LOW_LEVEL &&
intmode != GPIO_HIGH_LEVEL) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_value_invalid_arguments));
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
if (pull != PIN_TYPE_STD &&
pull != PIN_TYPE_STD_PU &&
@ -291,7 +291,7 @@ extint_obj_t* extint_register(mp_obj_t pin_obj, uint32_t intmode, uint32_t pull,
pull != PIN_TYPE_OD &&
pull != PIN_TYPE_OD_PU &&
pull != PIN_TYPE_OD_PD) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_value_invalid_arguments));
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
if (NULL == (self = extint_find(pin->port, pin->bit))) {

637
cc3200/mods/pybi2c.c Normal file
View File

@ -0,0 +1,637 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2013, 2014 Damien P. George
* Copyright (c) 2015 Daniel Campora
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdio.h>
#include <string.h>
#include "py/mpstate.h"
#include "mpconfig.h"
#include MICROPY_HAL_H
#include "nlr.h"
#include "misc.h"
#include "qstr.h"
#include "obj.h"
#include "runtime.h"
#include "bufhelper.h"
#include "inc/hw_types.h"
#include "inc/hw_i2c.h"
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "rom_map.h"
#include "pin.h"
#include "prcm.h"
#include "i2c.h"
#include "pybi2c.h"
#include "mpexception.h"
/// \moduleref pyb
/// \class I2C - a two-wire serial protocol
///
/// I2C is a two-wire protocol for communicating between devices. At the physical
/// level it consists of 2 wires: SCL and SDA, the clock and data lines respectively.
///
/// I2C objects are created attached to a specific bus. They can be initialised
/// when created, or initialised later on:
///
/// from pyb import I2C
///
/// i2c = I2C() # create
/// i2c = I2C(I2C.MASTER) # create and init as a master
/// i2c.init(I2C.MASTER, baudrate=20000) # init as a master
/// i2c.deinit() # turn off the peripheral
///
/// Printing the i2c object gives you information about its configuration.
///
/// Basic methods for slave are send and recv:
///
/// i2c.send('abc') # send 3 bytes
/// i2c.send(0x42) # send a single byte, given by the number
/// data = i2c.recv(3) # receive 3 bytes
///
/// To receive inplace, first create a bytearray:
///
/// data = bytearray(3) # create a buffer
/// i2c.recv(data) # receive 3 bytes, writing them into data
///
/// You can specify a timeout (in ms):
///
/// i2c.send(b'123', timeout=20) # timout after 20ms if the other end is not responding
///
/// A master must specify the recipient's address:
///
/// i2c.init(I2C.MASTER)
/// i2c.send('123', 0x42) # send 3 bytes to slave with address 0x42
/// i2c.send(b'456', addr=0x42) # keyword for address
///
/// Master also has other methods:
///
/// i2c.is_ready(0x42) # check if slave 0x42 is ready
/// i2c.scan() # scan for slaves on the bus, returning
/// # a list of valid addresses
/// i2c.mem_read(3, 0x42, 2) # read 3 bytes from memory of slave 0x42,
/// # starting at address 2 in the slave
/// i2c.mem_write('abc', 0x42, 2, timeout=10)
/******************************************************************************
DEFINE CONSTANTS
******************************************************************************/
#define PYBI2C_MODE_DISABLED (-1)
#define PYBI2C_MODE_MASTER (0)
#define PYBI2C_MODE_SLAVE (1)
#define PYBI2C_DEF_TIMEOUT_MS (7)
#define PYBI2C_TIMEOUT_TO_COUNT(to_ms, baud) (((baud) * to_ms) / 16000)
#define RET_IF_ERR(Func) { \
if (!Func) { \
return false; \
} \
}
/******************************************************************************
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
MAP_PRCMPeripheralClkEnable(PRCM_I2CA0, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
MAP_PRCMPeripheralReset(PRCM_I2CA0);
// Configure I2C module with the specified baudrate
MAP_I2CMasterInitExpClk(I2CA0_BASE, baudrate);
}
void i2c_deinit(void) {
MAP_I2CMasterDisable(I2CA0_BASE);
MAP_PRCMPeripheralClkDisable(PRCM_I2CA0, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
}
/******************************************************************************/
/* 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
MAP_I2CMasterIntClearEx(I2CA0_BASE, MAP_I2CMasterIntStatusEx(I2CA0_BASE, false));
// Set the time-out. Not to be used with breakpoints.
MAP_I2CMasterTimeoutSet(I2CA0_BASE, timeout);
// Initiate the transfer.
MAP_I2CMasterControl(I2CA0_BASE, cmd);
// Wait until the current byte has been transferred.
// Poll on the raw interrupt status.
while ((MAP_I2CMasterIntStatusEx(I2CA0_BASE, false) & (I2C_MASTER_INT_DATA | I2C_MASTER_INT_TIMEOUT)) == 0);
// Check for any errors in transfer
if (MAP_I2CMasterErr(I2CA0_BASE) != I2C_MASTER_ERR_NONE) {
switch(cmd) {
case I2C_MASTER_CMD_BURST_SEND_START:
case I2C_MASTER_CMD_BURST_SEND_CONT:
case I2C_MASTER_CMD_BURST_SEND_STOP:
MAP_I2CMasterControl(I2CA0_BASE, I2C_MASTER_CMD_BURST_SEND_ERROR_STOP);
break;
case I2C_MASTER_CMD_BURST_RECEIVE_START:
case I2C_MASTER_CMD_BURST_RECEIVE_CONT:
case I2C_MASTER_CMD_BURST_RECEIVE_FINISH:
MAP_I2CMasterControl(I2CA0_BASE, I2C_MASTER_CMD_BURST_RECEIVE_ERROR_STOP);
break;
default:
break;
}
return false;
}
return true;
}
STATIC bool pybI2C_Write(byte devAddr, byte *data, uint len, bool stop, uint timeout) {
// Set I2C codec slave address
MAP_I2CMasterSlaveAddrSet(I2CA0_BASE, devAddr, false);
// Write the first byte to the controller.
MAP_I2CMasterDataPut(I2CA0_BASE, *data++);
// Initiate the transfer.
RET_IF_ERR(pybI2C_transaction(I2C_MASTER_CMD_BURST_SEND_START, timeout));
// Loop until the completion of transfer or error
while (--len) {
// Write the next byte of data
MAP_I2CMasterDataPut(I2CA0_BASE, *data++);
// Transact over I2C to send the byte
RET_IF_ERR(pybI2C_transaction(I2C_MASTER_CMD_BURST_SEND_CONT, timeout));
}
// If a stop bit is to be sent, send it.
if (stop) {
RET_IF_ERR(pybI2C_transaction(I2C_MASTER_CMD_BURST_SEND_STOP, timeout));
}
return true;
}
STATIC bool pybI2C_Read(byte devAddr, byte *data, uint len, uint timeout) {
uint cmd;
// Set I2C codec slave address
MAP_I2CMasterSlaveAddrSet(I2CA0_BASE, devAddr, true);
// Check if its a single receive or burst receive
if (len > 1) {
// Initiate a burst receive sequence
cmd = I2C_MASTER_CMD_BURST_RECEIVE_START;
}
else {
// Configure for a single receive
cmd = I2C_MASTER_CMD_SINGLE_RECEIVE;
}
// Initiate the transfer.
RET_IF_ERR(pybI2C_transaction(cmd, timeout));
// Decrement the count
len--;
// Loop until the completion of reception or error
while (len) {
// Receive the byte over I2C
*data++ = MAP_I2CMasterDataGet(I2CA0_BASE);
if (--len) {
// Continue with reception
RET_IF_ERR(pybI2C_transaction(I2C_MASTER_CMD_BURST_RECEIVE_CONT, timeout));
}
else {
// Complete the last reception
RET_IF_ERR(pybI2C_transaction(I2C_MASTER_CMD_BURST_RECEIVE_FINISH, timeout));
}
}
// Receive the last byte over I2C
*data = MAP_I2CMasterDataGet(I2CA0_BASE);
return true;
}
STATIC bool pybI2C_ScanDevice(byte devAddr, uint timeout) {
// Set I2C codec slave address
MAP_I2CMasterSlaveAddrSet(I2CA0_BASE, devAddr, true);
// Initiate the transfer.
RET_IF_ERR(pybI2C_transaction(I2C_MASTER_CMD_SINGLE_RECEIVE, timeout));
// Since this is a hack, send the stop bit anyway
MAP_I2CMasterControl(I2CA0_BASE, I2C_MASTER_CMD_BURST_SEND_ERROR_STOP);
return true;
}
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");
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);
}
}
/// \method init(mode, *, addr=0x12, baudrate=400000)
///
/// Initialise the I2C bus with the given parameters:
///
/// - `mode` must be either `I2C.MASTER` or `I2C.SLAVE`
/// - `addr` is the 7-bit address (only sensible for a slave)
/// - `baudrate` is the SCL clock rate (only sensible for a master)
STATIC const mp_arg_t pyb_i2c_init_args[] = {
{ MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = PYBI2C_MODE_MASTER} },
{ MP_QSTR_addr, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} },
};
#define PYB_I2C_INIT_NUM_ARGS MP_ARRAY_SIZE(pyb_i2c_init_args)
STATIC mp_obj_t pyb_i2c_init_helper(pyb_i2c_obj_t *self_in, mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
pyb_i2c_obj_t *self = self_in;
// parse args
mp_arg_val_t vals[PYB_I2C_INIT_NUM_ARGS];
mp_arg_parse_all(n_args, args, kw_args, PYB_I2C_INIT_NUM_ARGS, pyb_i2c_init_args, vals);
self->mode = vals[0].u_int;
if (self->mode != PYBI2C_MODE_MASTER) {
// thrown an exception since only master mode is supported for now
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
if (self->mode == PYBI2C_MODE_SLAVE) {
self->slvaddr = vals[1].u_int;
}
else {
self->baudrate = MIN(vals[2].u_int, 400000);
}
// init the I2C bus
i2c_init(self->mode, self->slvaddr, self->baudrate);
return mp_const_none;
}
/// \classmethod \constructor(bus, ...)
///
/// Construct an I2C object on the given bus. `bus` can be 1.
/// 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.
/// See `init` for parameters of initialisation.
STATIC mp_obj_t pyb_i2c_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);
// get i2c number
mp_int_t i2c_id = mp_obj_get_int(args[0]) - 1;
// check 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);
}
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_i2c_init_helper(self, n_args - 1, args + 1, &kw_args);
}
return (mp_obj_t)self;
}
STATIC mp_obj_t pyb_i2c_init(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
return pyb_i2c_init_helper(args[0], n_args - 1, args + 1, kw_args);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_init_obj, 1, pyb_i2c_init);
/// \method deinit()
/// Turn off the I2C bus.
STATIC mp_obj_t pyb_i2c_deinit(mp_obj_t self_in) {
i2c_deinit();
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_i2c_deinit_obj, pyb_i2c_deinit);
/// \method is_ready(addr)
/// Check if an I2C device responds to the given address. Only valid when in master mode.
STATIC mp_obj_t pyb_i2c_is_ready(mp_obj_t self_in, mp_obj_t i2c_addr_o) {
pyb_i2c_obj_t *self = self_in;
if (self->mode != PYBI2C_MODE_MASTER) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible));
}
mp_uint_t i2c_addr = mp_obj_get_int(i2c_addr_o);
for (int i = 0; i < 10; i++) {
if (pybI2C_ScanDevice(i2c_addr, PYBI2C_TIMEOUT_TO_COUNT(PYBI2C_DEF_TIMEOUT_MS, self->baudrate))) {
return mp_const_true;
}
}
return mp_const_false;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_i2c_is_ready_obj, pyb_i2c_is_ready);
/// \method scan()
/// Scan all I2C addresses from 0x01 to 0x7f and return a list of those that respond.
/// Only valid when in master mode.
STATIC mp_obj_t pyb_i2c_scan(mp_obj_t self_in) {
pyb_i2c_obj_t *self = self_in;
if (self->mode != PYBI2C_MODE_MASTER) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible));
}
mp_obj_t list = mp_obj_new_list(0, NULL);
for (uint addr = 1; addr <= 127; addr++) {
for (int i = 0; i < 10; i++) {
if (pybI2C_ScanDevice(addr, PYBI2C_TIMEOUT_TO_COUNT(PYBI2C_DEF_TIMEOUT_MS, self->baudrate))) {
mp_obj_list_append(list, mp_obj_new_int(addr));
break;
}
}
}
return list;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_i2c_scan_obj, pyb_i2c_scan);
/// \method send(send, addr=0x00)
/// Send data on the bus:
///
/// - `send` is the data to send (an integer to send, or a buffer object)
/// - `addr` is the address to send to (only required in master mode)
/// - `timeout` is the timeout in milliseconds to wait for the other end to respond
/// Return value: `None`.
STATIC const mp_arg_t pyb_i2c_send_args[] = {
{ MP_QSTR_send, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_addr, MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5} },
};
#define PYB_I2C_SEND_NUM_ARGS MP_ARRAY_SIZE(pyb_i2c_send_args)
STATIC mp_obj_t pyb_i2c_send(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
pyb_i2c_obj_t *self = args[0];
// parse args
mp_arg_val_t vals[PYB_I2C_SEND_NUM_ARGS];
mp_arg_parse_all(n_args - 1, args + 1, kw_args, PYB_I2C_SEND_NUM_ARGS, pyb_i2c_send_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
if (self->mode == PYBI2C_MODE_MASTER) {
uint timeout = MIN(PYBI2C_TIMEOUT_TO_COUNT(vals[2].u_int, self->baudrate), 255);
if (!pybI2C_Write(vals[1].u_int, bufinfo.buf, bufinfo.len, true, timeout)) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
}
} else {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible));
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_send_obj, 1, pyb_i2c_send);
/// \method recv(recv, addr=0x00, timeout=10)
///
/// 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
/// - `addr` is the address to receive from (only required in master mode)
/// - `timeout` is the timeout in milliseconds to wait for the other end to respond
///
/// 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`.
STATIC const mp_arg_t pyb_i2c_recv_args[] = {
{ MP_QSTR_recv, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_addr, MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5} },
};
#define PYB_I2C_RECV_NUM_ARGS MP_ARRAY_SIZE(pyb_i2c_recv_args)
STATIC mp_obj_t pyb_i2c_recv(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
pyb_i2c_obj_t *self = args[0];
// parse args
mp_arg_val_t vals[PYB_I2C_RECV_NUM_ARGS];
mp_arg_parse_all(n_args - 1, args + 1, kw_args, PYB_I2C_RECV_NUM_ARGS, pyb_i2c_recv_args, vals);
// get the buffer to receive into
vstr_t vstr;
mp_obj_t o_ret = pyb_buf_get_for_recv(vals[0].u_obj, &vstr);
// receive the data
if (self->mode == PYBI2C_MODE_MASTER) {
uint timeout = MIN(PYBI2C_TIMEOUT_TO_COUNT(vals[2].u_int, self->baudrate), 255);
if (!pybI2C_Read(vals[1].u_int, (byte *)vstr.buf, vstr.len, timeout)) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
}
} else {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible));
}
// 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);
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_recv_obj, 1, pyb_i2c_recv);
/// \method mem_read(data, addr, memaddr, timeout=10, addr_size=8)
///
/// Read from the memory of an I2C device:
///
/// - `data` can be an integer or a buffer to read into
/// - `addr` is the I2C device address
/// - `memaddr` is the memory location within the I2C device
/// - `timeout` is the timeout in milliseconds to wait for the other end to respond
/// - `addr_size` selects width of memaddr: 8 or 16 bits
///
/// Returns the read data.
/// This is only valid in master mode.
STATIC const mp_arg_t pyb_i2c_mem_read_args[] = {
{ MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5} },
{ MP_QSTR_addr_size, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
};
#define PYB_I2C_MEM_READ_NUM_ARGS MP_ARRAY_SIZE(pyb_i2c_mem_read_args)
STATIC mp_obj_t pyb_i2c_mem_read(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
pyb_i2c_obj_t *self = args[0];
if (self->mode != PYBI2C_MODE_MASTER) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible));
}
// parse args
mp_arg_val_t vals[PYB_I2C_MEM_READ_NUM_ARGS];
mp_arg_parse_all(n_args - 1, args + 1, kw_args, PYB_I2C_MEM_READ_NUM_ARGS, pyb_i2c_mem_read_args, vals);
// get the buffer to read into
vstr_t vstr;
mp_obj_t o_ret = pyb_buf_get_for_recv(vals[0].u_obj, &vstr);
// get the addresses
mp_uint_t i2c_addr = vals[1].u_int;
mp_uint_t mem_addr = vals[2].u_int;
// determine width of mem_addr (1 or 2 bytes)
mp_uint_t mem_addr_size = vals[4].u_int >> 3;
// Write the register address to be read from.
uint timeout = MIN(PYBI2C_TIMEOUT_TO_COUNT(vals[3].u_int, self->baudrate), 255);
if (pybI2C_Write (i2c_addr, (byte *)&mem_addr, mem_addr_size, false, timeout)) {
// Read the specified length of data
if (pybI2C_Read (i2c_addr, (byte *)vstr.buf, vstr.len, timeout)) {
// return the read data
if (o_ret != MP_OBJ_NULL) {
return o_ret;
} else {
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
}
}
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_mem_read_obj, 1, pyb_i2c_mem_read);
/// \method mem_write(data, addr, memaddr, timeout=10, addr_size=8)
///
/// Write to the memory of an I2C device:
///
/// - `data` can be an integer or a buffer to write from
/// - `addr` is the I2C device address
/// - `memaddr` is the memory location within the I2C device
/// - `timeout` is the timeout in milliseconds to wait for the other end to respond
/// - `addr_size` selects width of memaddr: 8 or 16 bits
///
/// Returns `None`.
/// This is only valid in master mode.
STATIC mp_obj_t pyb_i2c_mem_write(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
pyb_i2c_obj_t *self = args[0];
if (self->mode != PYBI2C_MODE_MASTER) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible));
}
// parse args (same as mem_read)
mp_arg_val_t vals[PYB_I2C_MEM_READ_NUM_ARGS];
mp_arg_parse_all(n_args - 1, args + 1, kw_args, PYB_I2C_MEM_READ_NUM_ARGS, pyb_i2c_mem_read_args, vals);
// get the buffer to write from
mp_buffer_info_t bufinfo;
uint8_t data[1];
pyb_buf_get_for_send(vals[0].u_obj, &bufinfo, data);
// get the addresses
mp_uint_t i2c_addr = vals[1].u_int;
mp_uint_t mem_addr = vals[2].u_int;
// determine width of mem_addr (1 or 2 bytes)
mp_uint_t mem_addr_size = vals[4].u_int >> 3;
// Write the register address to be write to.
uint timeout = MIN(PYBI2C_TIMEOUT_TO_COUNT(vals[2].u_int, self->baudrate), 255);
if (pybI2C_Write (i2c_addr, (byte *)&mem_addr, mem_addr_size, false, timeout)) {
// Write the specified length of data
if (pybI2C_Write (i2c_addr, bufinfo.buf, bufinfo.len, true, timeout)) {
return mp_const_none;
}
}
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
return mp_const_none;
}
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_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 },
{ MP_OBJ_NEW_QSTR(MP_QSTR_scan), (mp_obj_t)&pyb_i2c_scan_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_send), (mp_obj_t)&pyb_i2c_send_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&pyb_i2c_recv_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_mem_read), (mp_obj_t)&pyb_i2c_mem_read_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_mem_write), (mp_obj_t)&pyb_i2c_mem_write_obj },
// class constants
/// \constant MASTER - for initialising the bus to master mode
/// \constant SLAVE - for initialising the bus to slave mode
{ MP_OBJ_NEW_QSTR(MP_QSTR_MASTER), MP_OBJ_NEW_SMALL_INT(PYBI2C_MODE_MASTER) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SLAVE), MP_OBJ_NEW_SMALL_INT(PYBI2C_MODE_SLAVE) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_i2c_locals_dict, pyb_i2c_locals_dict_table);
const mp_obj_type_t pyb_i2c_type = {
{ &mp_type_type },
.name = MP_QSTR_I2C,
.print = pyb_i2c_print,
.make_new = pyb_i2c_make_new,
.locals_dict = (mp_obj_t)&pyb_i2c_locals_dict,
};

32
cc3200/mods/pybi2c.h Normal file
View File

@ -0,0 +1,32 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2013, 2014 Damien P. George
* Copyright (c) 2015 Daniel Campora
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
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);

View File

@ -71,11 +71,16 @@
///
/// g = pyb.Pin('GPIO9', 0)
///
/// And finally, you can also pass a pin number directly:
///
/// g = pyb.Pin(64, 0)
///
/// To summarise, the following order determines how things get mapped into
/// an ordinal pin number:
///
/// 1. Directly specify a Pin object
/// 2. Supply a string which matches a CPU port/pin
/// 2. Supply a string which matches a CPU pin name
/// 3. Provide a pin number
void pin_init0(void) {
}
@ -96,6 +101,16 @@ const pin_obj_t *pin_find(mp_obj_t user_obj) {
return pin_obj;
}
// See if the pin number matches a cpu pin
mp_int_t pin_num;
if (mp_obj_get_int_maybe(user_obj, &pin_num)) {
// The Pins dictionary has pin indexes, so we must substract one from the value passed
pin_obj = pin_find_pin(&pin_cpu_pins_locals_dict, (pin_num - 1));
if (pin_obj) {
return pin_obj;
}
}
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
@ -218,9 +233,9 @@ STATIC mp_obj_t pin_make_new(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw,
/// - `Pin.OD_PD` - open drain with pull-down resistor.
/// - `Pin.ANALOG` - configured in analog (adc) mode
/// - `strength` can be one of:
/// - `Pin.2MA` - 2ma drive strength;
/// - `Pin.4MA` - 4ma drive strength;
/// - `Pin.6MA` - 6ma drive strength;
/// - `Pin.S2MA` - 2ma drive strength;
/// - `Pin.S4MA` - 4ma drive strength;
/// - `Pin.S6MA` - 6ma drive strength;
///
/// Returns: `None`.
STATIC const mp_arg_t pin_init_args[] = {

View File

@ -60,6 +60,7 @@ void pin_init0(void);
void pin_config(const pin_obj_t *self, uint af, uint mode, uint type, uint strength);
const pin_obj_t *pin_find(mp_obj_t user_obj);
const pin_obj_t *pin_find_named_pin(const mp_obj_dict_t *named_pins, mp_obj_t name);
const pin_obj_t *pin_find_pin(const mp_obj_dict_t *named_pins, uint pin_num);
uint32_t pin_get_mode(const pin_obj_t *self);
uint32_t pin_get_type(const pin_obj_t *self);
uint32_t pin_get_strenght(const pin_obj_t *self);

View File

@ -41,22 +41,18 @@
#include "runtime.h"
#include "stream.h"
#include "inc/hw_types.h"
#include "inc/hw_gpio.h"
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_uart.h"
#include "rom_map.h"
#include "interrupt.h"
#include "prcm.h"
#include "gpio.h"
#include "uart.h"
#include "pin.h"
#include "pybuart.h"
#include "pybioctl.h"
#include "mpexception.h"
#include "osi.h"
/// \moduleref pyb
/// \class UART - duplex serial communication bus
///
@ -90,8 +86,6 @@
///
/// uart.any() # returns True if any characters waiting
/******************************************************************************
DECLARE PRIVATE FUNCTIONS
******************************************************************************/
@ -150,16 +144,12 @@ bool uart_init2(pyb_uart_obj_t *self) {
case PYB_UART_1:
self->reg = UARTA0_BASE;
uartPerh = PRCM_UARTA0;
MAP_PinTypeUART(PIN_55, PIN_MODE_3);
MAP_PinTypeUART(PIN_57, PIN_MODE_3);
MAP_UARTIntRegister(UARTA0_BASE, UART0IntHandler);
MAP_IntPrioritySet(INT_UARTA0, INT_PRIORITY_LVL_7);
break;
case PYB_UART_2:
self->reg = UARTA1_BASE;
uartPerh = PRCM_UARTA1;
MAP_PinTypeUART(PIN_58, PIN_MODE_6);
MAP_PinTypeUART(PIN_59, PIN_MODE_6);
MAP_UARTIntRegister(UARTA1_BASE, UART1IntHandler);
MAP_IntPrioritySet(INT_UARTA1, INT_PRIORITY_LVL_7);
break;
@ -469,9 +459,10 @@ STATIC mp_obj_t pyb_uart_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t
pyb_uart_obj_t *self;
if (MP_STATE_PORT(pyb_uart_obj_all)[uart_id - 1] == NULL) {
// create new UART object
self = m_new0(pyb_uart_obj_t, 1);
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 {

View File

@ -123,6 +123,7 @@ extern const struct _mp_obj_module_t mp_module_network;
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 mod_network_nic_list; \

View File

@ -41,6 +41,8 @@
#include "runtime.h"
#include "repl.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "pin.h"
#include "pybuart.h"
#include "pybpin.h"
#include "pybrtc.h"
@ -64,6 +66,8 @@
#include "mpexception.h"
#include "random.h"
#include "pybextint.h"
#include "pybi2c.h"
#include "pins.h"
/******************************************************************************
DECLARE PRIVATE CONSTANTS
@ -142,7 +146,13 @@ 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
pin_config(&pin_GPIO1, PIN_MODE_3, 0, PIN_TYPE_STD, PIN_STRENGTH_2MA);
pin_config(&pin_GPIO2, PIN_MODE_3, 0, PIN_TYPE_STD, PIN_STRENGTH_2MA);
// Instantiate the stdio uart
mp_obj_t args[2] = {
mp_obj_new_int(MICROPY_STDIO_UART),
@ -151,7 +161,6 @@ soft_reset:
MP_STATE_PORT(pyb_stdio_uart) = pyb_uart_type.make_new((mp_obj_t)&pyb_uart_type, MP_ARRAY_SIZE(args), 0, args);
readline_init0();
pin_init0();
extint_init0();
mod_network_init();
wlan_init0();

View File

@ -58,6 +58,7 @@ Q(chdir)
Q(getcwd)
Q(listdir)
Q(mkdir)
Q(mkdisk)
Q(remove)
Q(rmdir)
Q(unlink)
@ -135,6 +136,26 @@ Q(FLOW_TX)
Q(FLOW_RX)
Q(FLOW_TXRX)
// for I2C class
Q(I2C)
Q(mode)
Q(addr)
Q(baudrate)
Q(data)
Q(memaddr)
Q(addr_size)
Q(timeout)
Q(init)
Q(deinit)
Q(is_ready)
Q(scan)
Q(send)
Q(recv)
Q(mem_read)
Q(mem_write)
Q(MASTER)
Q(SLAVE)
// for RTC class
Q(RTC)
Q(datetime)