Skip to content

Commit 6cfda30

Browse files
committed
stmhal: Add I2C support; change accel driver to use new I2C.
1 parent 681d0a9 commit 6cfda30

7 files changed

Lines changed: 212 additions & 47 deletions

File tree

stmhal/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,9 @@ SRC_C = \
9494
servo.c \
9595
dac.c \
9696
adc.c \
97+
i2c.c \
9798

9899
# timer.c \
99-
# i2c.c \
100100
# pybwlan.c \
101101
102102
SRC_S = \

stmhal/accel.c

Lines changed: 13 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "qstr.h"
1010
#include "obj.h"
1111
#include "runtime.h"
12+
#include "i2c.h"
1213
#include "accel.h"
1314

1415
#define MMA_ADDR (0x98)
@@ -19,8 +20,6 @@
1920
#define MMA_REG_MODE (7)
2021
#define MMA_AXIS_SIGNED_VALUE(i) (((i) & 0x3f) | ((i) & 0x20 ? (~0x1f) : 0))
2122

22-
STATIC I2C_HandleTypeDef I2cHandle;
23-
2423
void accel_init(void) {
2524
GPIO_InitTypeDef GPIO_InitStructure;
2625

@@ -31,38 +30,12 @@ void accel_init(void) {
3130
GPIO_InitStructure.Speed = GPIO_SPEED_LOW;
3231
GPIO_InitStructure.Pull = GPIO_NOPULL;
3332
HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
34-
35-
// PB6=SCL, PB7=SDA
36-
GPIO_InitStructure.Pin = GPIO_PIN_6 | GPIO_PIN_7;
37-
GPIO_InitStructure.Mode = GPIO_MODE_AF_OD;
38-
GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
39-
GPIO_InitStructure.Pull = GPIO_NOPULL; // have external pull-up resistors on both lines
40-
GPIO_InitStructure.Alternate = GPIO_AF4_I2C1;
41-
HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
42-
43-
// enable the I2C1 clock
44-
__I2C1_CLK_ENABLE();
45-
46-
// set up the I2C1 device
47-
memset(&I2cHandle, 0, sizeof(I2C_HandleTypeDef));
48-
I2cHandle.Instance = I2C1;
49-
I2cHandle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
50-
I2cHandle.Init.ClockSpeed = 400000;
51-
I2cHandle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLED;
52-
I2cHandle.Init.DutyCycle = I2C_DUTYCYCLE_16_9;
53-
I2cHandle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLED;
54-
I2cHandle.Init.NoStretchMode = I2C_NOSTRETCH_DISABLED;
55-
I2cHandle.Init.OwnAddress1 = 0xfe; // unused
56-
I2cHandle.Init.OwnAddress2 = 0xfe; // unused
57-
58-
if (HAL_I2C_Init(&I2cHandle) != HAL_OK) {
59-
// init error
60-
printf("accel_init: HAL_I2C_Init failed\n");
61-
return;
62-
}
6333
}
6434

65-
STATIC void accel_init_device(void) {
35+
STATIC void accel_start(void) {
36+
// start the I2C bus
37+
i2c_start(&I2cHandle_X);
38+
6639
// turn off AVDD, wait 20ms, turn on AVDD, wait 20ms again
6740
GPIOB->BSRRH = GPIO_PIN_5; // turn off
6841
HAL_Delay(20);
@@ -73,7 +46,7 @@ STATIC void accel_init_device(void) {
7346

7447
//printf("IsDeviceReady\n");
7548
for (int i = 0; i < 10; i++) {
76-
status = HAL_I2C_IsDeviceReady(&I2cHandle, MMA_ADDR, 10, 200);
49+
status = HAL_I2C_IsDeviceReady(&I2cHandle_X, MMA_ADDR, 10, 200);
7750
//printf(" got %d\n", status);
7851
if (status == HAL_OK) {
7952
break;
@@ -83,7 +56,7 @@ STATIC void accel_init_device(void) {
8356
//printf("MemWrite\n");
8457
uint8_t data[1];
8558
data[0] = 1; // active mode
86-
status = HAL_I2C_Mem_Write(&I2cHandle, MMA_ADDR, MMA_REG_MODE, I2C_MEMADD_SIZE_8BIT, data, 1, 200);
59+
status = HAL_I2C_Mem_Write(&I2cHandle_X, MMA_ADDR, MMA_REG_MODE, I2C_MEMADD_SIZE_8BIT, data, 1, 200);
8760
//printf(" got %d\n", status);
8861
}
8962

@@ -108,14 +81,14 @@ STATIC mp_obj_t pyb_accel_make_new(mp_obj_t type_in, uint n_args, uint n_kw, con
10881

10982
// init accel object
11083
pyb_accel_obj.base.type = &pyb_accel_type;
111-
accel_init_device();
84+
accel_start();
11285

11386
return &pyb_accel_obj;
11487
}
11588

11689
STATIC mp_obj_t read_axis(int axis) {
11790
uint8_t data[1];
118-
HAL_I2C_Mem_Read(&I2cHandle, MMA_ADDR, axis, I2C_MEMADD_SIZE_8BIT, data, 1, 200);
91+
HAL_I2C_Mem_Read(&I2cHandle_X, MMA_ADDR, axis, I2C_MEMADD_SIZE_8BIT, data, 1, 200);
11992
return mp_obj_new_int(MMA_AXIS_SIGNED_VALUE(data[0]));
12093
}
12194

@@ -139,7 +112,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_accel_z_obj, pyb_accel_z);
139112

140113
STATIC mp_obj_t pyb_accel_tilt(mp_obj_t self_in) {
141114
uint8_t data[1];
142-
HAL_I2C_Mem_Read(&I2cHandle, MMA_ADDR, MMA_REG_TILT, I2C_MEMADD_SIZE_8BIT, data, 1, 200);
115+
HAL_I2C_Mem_Read(&I2cHandle_X, MMA_ADDR, MMA_REG_TILT, I2C_MEMADD_SIZE_8BIT, data, 1, 200);
143116
return mp_obj_new_int(data[0]);
144117
}
145118

@@ -151,7 +124,7 @@ STATIC mp_obj_t pyb_accel_filtered_xyz(mp_obj_t self_in) {
151124
memmove(self->buf, self->buf + NUM_AXIS, NUM_AXIS * (FILT_DEPTH - 1) * sizeof(int16_t));
152125

153126
uint8_t data[NUM_AXIS];
154-
HAL_I2C_Mem_Read(&I2cHandle, MMA_ADDR, MMA_REG_X, I2C_MEMADD_SIZE_8BIT, data, NUM_AXIS, 200);
127+
HAL_I2C_Mem_Read(&I2cHandle_X, MMA_ADDR, MMA_REG_X, I2C_MEMADD_SIZE_8BIT, data, NUM_AXIS, 200);
155128

156129
mp_obj_t tuple[NUM_AXIS];
157130
for (int i = 0; i < NUM_AXIS; i++) {
@@ -170,7 +143,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_accel_filtered_xyz_obj, pyb_accel_filtered_
170143

171144
STATIC mp_obj_t pyb_accel_read_reg(mp_obj_t self_in, mp_obj_t reg) {
172145
uint8_t data[1];
173-
HAL_I2C_Mem_Read(&I2cHandle, MMA_ADDR, mp_obj_get_int(reg), I2C_MEMADD_SIZE_8BIT, data, 1, 200);
146+
HAL_I2C_Mem_Read(&I2cHandle_X, MMA_ADDR, mp_obj_get_int(reg), I2C_MEMADD_SIZE_8BIT, data, 1, 200);
174147
return mp_obj_new_int(data[0]);
175148
}
176149

@@ -179,7 +152,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(pyb_accel_read_reg_obj, pyb_accel_read_reg);
179152
STATIC mp_obj_t pyb_accel_write_reg(mp_obj_t self_in, mp_obj_t reg, mp_obj_t val) {
180153
uint8_t data[1];
181154
data[0] = mp_obj_get_int(val);
182-
HAL_I2C_Mem_Write(&I2cHandle, MMA_ADDR, mp_obj_get_int(reg), I2C_MEMADD_SIZE_8BIT, data, 1, 200);
155+
HAL_I2C_Mem_Write(&I2cHandle_X, MMA_ADDR, mp_obj_get_int(reg), I2C_MEMADD_SIZE_8BIT, data, 1, 200);
183156
return mp_const_none;
184157
}
185158

stmhal/accel.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1-
void accel_init(void);
2-
1+
extern I2C_HandleTypeDef I2cHandle;
32
extern const mp_obj_type_t pyb_accel_type;
3+
4+
void accel_init(void);

stmhal/i2c.c

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
#include <stdio.h>
2+
#include <string.h>
3+
4+
#include <stm32f4xx_hal.h>
5+
6+
#include "nlr.h"
7+
#include "misc.h"
8+
#include "mpconfig.h"
9+
#include "qstr.h"
10+
#include "obj.h"
11+
#include "runtime.h"
12+
#include "i2c.h"
13+
14+
I2C_HandleTypeDef I2cHandle_X;
15+
I2C_HandleTypeDef I2cHandle_Y;
16+
17+
void i2c_init(void) {
18+
// init the I2C1 device
19+
memset(&I2cHandle_X, 0, sizeof(I2C_HandleTypeDef));
20+
I2cHandle_X.Instance = I2C1;
21+
22+
// init the I2C2 device
23+
memset(&I2cHandle_Y, 0, sizeof(I2C_HandleTypeDef));
24+
I2cHandle_Y.Instance = I2C2;
25+
}
26+
27+
void i2c_start(I2C_HandleTypeDef *i2c_handle) {
28+
GPIO_InitTypeDef GPIO_InitStructure;
29+
30+
// init the GPIO lines
31+
GPIO_InitStructure.Mode = GPIO_MODE_AF_OD;
32+
GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
33+
GPIO_InitStructure.Pull = GPIO_NOPULL; // have external pull-up resistors on both lines
34+
35+
if (i2c_handle == &I2cHandle_X) {
36+
// X-skin: X9=PB6=SCL, X10=PB7=SDA
37+
GPIO_InitStructure.Pin = GPIO_PIN_6 | GPIO_PIN_7;
38+
GPIO_InitStructure.Alternate = GPIO_AF4_I2C1;
39+
HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
40+
// enable the I2C clock
41+
__I2C1_CLK_ENABLE();
42+
} else {
43+
// Y-skin: Y9=PB10=SCL, Y10=PB11=SDA
44+
GPIO_InitStructure.Pin = GPIO_PIN_10 | GPIO_PIN_11;
45+
GPIO_InitStructure.Alternate = GPIO_AF4_I2C2;
46+
HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
47+
// enable the I2C clock
48+
__I2C2_CLK_ENABLE();
49+
}
50+
51+
// init the I2C device
52+
i2c_handle->Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
53+
i2c_handle->Init.ClockSpeed = 400000;
54+
i2c_handle->Init.DualAddressMode = I2C_DUALADDRESS_DISABLED;
55+
i2c_handle->Init.DutyCycle = I2C_DUTYCYCLE_16_9;
56+
i2c_handle->Init.GeneralCallMode = I2C_GENERALCALL_DISABLED;
57+
i2c_handle->Init.NoStretchMode = I2C_NOSTRETCH_DISABLED;
58+
i2c_handle->Init.OwnAddress1 = 0xfe; // unused
59+
i2c_handle->Init.OwnAddress2 = 0xfe; // unused
60+
61+
if (HAL_I2C_Init(i2c_handle) != HAL_OK) {
62+
// init error
63+
printf("accel_init: HAL_I2C_Init failed\n");
64+
return;
65+
}
66+
}
67+
68+
/******************************************************************************/
69+
/* Micro Python bindings */
70+
71+
#define PYB_NUM_I2C (2)
72+
73+
typedef struct _pyb_i2c_obj_t {
74+
mp_obj_base_t base;
75+
I2C_HandleTypeDef *i2c_handle;
76+
} pyb_i2c_obj_t;
77+
78+
STATIC pyb_i2c_obj_t pyb_i2c_obj[PYB_NUM_I2C] = {{{&pyb_i2c_type}, &I2cHandle_X}, {{&pyb_i2c_type}, &I2cHandle_Y}};
79+
80+
STATIC mp_obj_t pyb_i2c_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
81+
// check arguments
82+
if (!(n_args == 1 && n_kw == 0)) {
83+
nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "I2C accepts 1 argument"));
84+
}
85+
86+
// get i2c number
87+
machine_int_t i2c_id = mp_obj_get_int(args[0]) - 1;
88+
89+
// check i2c number
90+
if (!(0 <= i2c_id && i2c_id < PYB_NUM_I2C)) {
91+
nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "I2C bus %d does not exist", i2c_id + 1));
92+
}
93+
94+
// get i2c object
95+
pyb_i2c_obj_t *i2c_obj = &pyb_i2c_obj[i2c_id];
96+
97+
// start the peripheral
98+
i2c_start(i2c_obj->i2c_handle);
99+
100+
return &pyb_i2c_obj;
101+
}
102+
103+
STATIC mp_obj_t pyb_i2c_is_ready(mp_obj_t self_in, mp_obj_t i2c_addr_o) {
104+
pyb_i2c_obj_t *self = self_in;
105+
machine_uint_t i2c_addr = mp_obj_get_int(i2c_addr_o) << 1;
106+
107+
//printf("IsDeviceReady\n");
108+
for (int i = 0; i < 10; i++) {
109+
HAL_StatusTypeDef status = HAL_I2C_IsDeviceReady(self->i2c_handle, i2c_addr, 10, 200);
110+
//printf(" got %d\n", status);
111+
if (status == HAL_OK) {
112+
return mp_const_true;
113+
}
114+
}
115+
116+
return mp_const_false;
117+
}
118+
119+
STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_i2c_is_ready_obj, pyb_i2c_is_ready);
120+
121+
STATIC mp_obj_t pyb_i2c_mem_read(uint n_args, const mp_obj_t *args) {
122+
pyb_i2c_obj_t *self = args[0];
123+
machine_uint_t i2c_addr = mp_obj_get_int(args[1]) << 1;
124+
machine_uint_t mem_addr = mp_obj_get_int(args[2]);
125+
machine_uint_t n = mp_obj_get_int(args[3]);
126+
127+
byte *data;
128+
mp_obj_t o = mp_obj_str_builder_start(&bytes_type, n, &data);
129+
HAL_StatusTypeDef status = HAL_I2C_Mem_Read(self->i2c_handle, i2c_addr, mem_addr, I2C_MEMADD_SIZE_8BIT, data, n, 200);
130+
131+
//printf("Read got %d\n", status);
132+
133+
if (status != HAL_OK) {
134+
// TODO really need a HardwareError object, or something
135+
nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_Exception, "HAL_I2C_Mem_Read failed with code %d", status));
136+
}
137+
138+
return mp_obj_str_builder_end(o);
139+
}
140+
141+
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_i2c_mem_read_obj, 4, 4, pyb_i2c_mem_read);
142+
143+
STATIC mp_obj_t pyb_i2c_mem_write(uint n_args, const mp_obj_t *args) {
144+
pyb_i2c_obj_t *self = args[0];
145+
machine_uint_t i2c_addr = mp_obj_get_int(args[1]) << 1;
146+
machine_uint_t mem_addr = mp_obj_get_int(args[2]);
147+
HAL_StatusTypeDef status;
148+
mp_obj_type_t *type = mp_obj_get_type(args[3]);
149+
if (type->buffer_p.get_buffer != NULL) {
150+
buffer_info_t bufinfo;
151+
type->buffer_p.get_buffer(args[3], &bufinfo, BUFFER_READ);
152+
status = HAL_I2C_Mem_Write(self->i2c_handle, i2c_addr, mem_addr, I2C_MEMADD_SIZE_8BIT, bufinfo.buf, bufinfo.len, 200);
153+
} else if (MP_OBJ_IS_INT(args[3])) {
154+
uint8_t data[1] = {mp_obj_get_int(args[3])};
155+
status = HAL_I2C_Mem_Write(self->i2c_handle, i2c_addr, mem_addr, I2C_MEMADD_SIZE_8BIT, data, 1, 200);
156+
} else {
157+
nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "data argument must be an integer or support the buffer protocol"));
158+
}
159+
160+
//printf("Write got %d\n", status);
161+
162+
if (status != HAL_OK) {
163+
// TODO really need a HardwareError object, or something
164+
nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_Exception, "HAL_I2C_Mem_Write failed with code %d", status));
165+
}
166+
167+
return mp_const_none;
168+
}
169+
170+
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_i2c_mem_write_obj, 4, 4, pyb_i2c_mem_write);
171+
172+
STATIC const mp_method_t pyb_i2c_methods[] = {
173+
{ "is_ready", &pyb_i2c_is_ready_obj },
174+
{ "mem_read", &pyb_i2c_mem_read_obj },
175+
{ "mem_write", &pyb_i2c_mem_write_obj },
176+
{ NULL, NULL },
177+
};
178+
179+
const mp_obj_type_t pyb_i2c_type = {
180+
{ &mp_type_type },
181+
.name = MP_QSTR_I2C,
182+
.make_new = pyb_i2c_make_new,
183+
.methods = pyb_i2c_methods,
184+
};

stmhal/i2c.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
extern I2C_HandleTypeDef I2cHandle_X;
2+
extern I2C_HandleTypeDef I2cHandle_Y;
3+
extern const mp_obj_type_t pyb_i2c_type;
4+
5+
void i2c_init(void);
6+
void i2c_start(I2C_HandleTypeDef *i2c_handle);

stmhal/main.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "sdcard.h"
3333
#include "ff.h"
3434
#include "lcd.h"
35+
#include "i2c.h"
3536
#include "accel.h"
3637
#include "servo.h"
3738
#include "dac.h"
@@ -375,6 +376,8 @@ int main(void) {
375376
pyb_usb_dev_init(USBD_DEVICE_CDC_MSC, usbd_medium_kind);
376377
#endif
377378

379+
i2c_init();
380+
378381
#if MICROPY_HW_HAS_MMA7660
379382
// MMA accel: init and reset
380383
accel_init();

stmhal/modpyb.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@
2626
#include "accel.h"
2727
#include "servo.h"
2828
#include "dac.h"
29+
#include "i2c.h"
2930
#if 0
3031
#include "usb.h"
31-
#include "i2c.h"
3232
#endif
3333
#include "modpyb.h"
3434
#include "ff.h"
@@ -261,9 +261,7 @@ STATIC const mp_map_elem_t pyb_module_globals_table[] = {
261261
{ MP_OBJ_NEW_QSTR(MP_QSTR_hid), (mp_obj_t)&pyb_hid_send_report_obj },
262262
#endif
263263
{ MP_OBJ_NEW_QSTR(MP_QSTR_Led), (mp_obj_t)&pyb_led_type },
264-
#if 0
265-
{ MP_OBJ_NEW_QSTR(MP_QSTR_I2C), (mp_obj_t)&pyb_I2C_obj },
266-
#endif
264+
{ MP_OBJ_NEW_QSTR(MP_QSTR_I2C), (mp_obj_t)&pyb_i2c_type },
267265
{ MP_OBJ_NEW_QSTR(MP_QSTR_Usart), (mp_obj_t)&pyb_Usart_obj },
268266

269267
{ MP_OBJ_NEW_QSTR(MP_QSTR_ADC), (mp_obj_t)&pyb_adc_type },

0 commit comments

Comments
 (0)