Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
TASTE
uPython-mirror
Commits
eb8bdf4d
Commit
eb8bdf4d
authored
Apr 21, 2014
by
Damien George
Browse files
stmhal, SPI and I2C: Improvements to functionality and consistency.
parent
64ba6ca1
Changes
8
Show whitespace changes
Inline
Side-by-side
stmhal/Makefile
View file @
eb8bdf4d
...
...
@@ -97,6 +97,7 @@ SRC_C = \
servo.c
\
dac.c
\
adc.c
\
bufhelper.c
\
i2c.c
\
spi.c
\
...
...
stmhal/accel.c
View file @
eb8bdf4d
...
...
@@ -35,7 +35,15 @@ void accel_init(void) {
}
STATIC
void
accel_start
(
void
)
{
// start the I2C bus
// start the I2C bus in master mode
I2CHandle1
.
Init
.
AddressingMode
=
I2C_ADDRESSINGMODE_7BIT
;
I2CHandle1
.
Init
.
ClockSpeed
=
400000
;
I2CHandle1
.
Init
.
DualAddressMode
=
I2C_DUALADDRESS_DISABLED
;
I2CHandle1
.
Init
.
DutyCycle
=
I2C_DUTYCYCLE_16_9
;
I2CHandle1
.
Init
.
GeneralCallMode
=
I2C_GENERALCALL_DISABLED
;
I2CHandle1
.
Init
.
NoStretchMode
=
I2C_NOSTRETCH_DISABLED
;
I2CHandle1
.
Init
.
OwnAddress1
=
PYB_I2C_MASTER_ADDRESS
;
I2CHandle1
.
Init
.
OwnAddress2
=
0xfe
;
// unused
i2c_init
(
&
I2CHandle1
);
// turn off AVDD, wait 20ms, turn on AVDD, wait 20ms again
...
...
stmhal/bufhelper.c
0 → 100644
View file @
eb8bdf4d
#include
"misc.h"
#include
"mpconfig.h"
#include
"qstr.h"
#include
"obj.h"
#include
"bufhelper.h"
void
pyb_buf_get_for_send
(
mp_obj_t
o
,
mp_buffer_info_t
*
bufinfo
,
uint8_t
*
tmp_data
)
{
if
(
MP_OBJ_IS_INT
(
o
))
{
tmp_data
[
0
]
=
mp_obj_get_int
(
o
);
bufinfo
->
buf
=
tmp_data
;
bufinfo
->
len
=
1
;
bufinfo
->
typecode
=
'B'
;
}
else
{
mp_get_buffer_raise
(
o
,
bufinfo
,
MP_BUFFER_READ
);
}
}
mp_obj_t
pyb_buf_get_for_recv
(
mp_obj_t
o
,
mp_buffer_info_t
*
bufinfo
)
{
if
(
MP_OBJ_IS_INT
(
o
))
{
// allocate a new bytearray of given length
bufinfo
->
len
=
mp_obj_get_int
(
o
);
bufinfo
->
typecode
=
'B'
;
return
mp_obj_str_builder_start
(
&
mp_type_bytes
,
bufinfo
->
len
,
(
byte
**
)
&
bufinfo
->
buf
);
}
else
{
// get the existing buffer
mp_get_buffer_raise
(
o
,
bufinfo
,
MP_BUFFER_WRITE
);
return
MP_OBJ_NULL
;
}
}
stmhal/bufhelper.h
0 → 100644
View file @
eb8bdf4d
void
pyb_buf_get_for_send
(
mp_obj_t
o
,
mp_buffer_info_t
*
bufinfo
,
uint8_t
*
tmp_data
);
mp_obj_t
pyb_buf_get_for_recv
(
mp_obj_t
o
,
mp_buffer_info_t
*
bufinfo
);
stmhal/i2c.c
View file @
eb8bdf4d
...
...
@@ -11,8 +11,12 @@
#include
"runtime.h"
#include
"pin.h"
#include
"genhdr/pins.h"
#include
"bufhelper.h"
#include
"i2c.h"
#define PYB_I2C_MASTER (0)
#define PYB_I2C_SLAVE (1)
#if MICROPY_HW_ENABLE_I2C1
I2C_HandleTypeDef
I2CHandle1
=
{.
Instance
=
NULL
};
#endif
...
...
@@ -65,15 +69,6 @@ void i2c_init(I2C_HandleTypeDef *i2c) {
}
// init the I2C device
i2c
->
Init
.
AddressingMode
=
I2C_ADDRESSINGMODE_7BIT
;
i2c
->
Init
.
ClockSpeed
=
400000
;
i2c
->
Init
.
DualAddressMode
=
I2C_DUALADDRESS_DISABLED
;
i2c
->
Init
.
DutyCycle
=
I2C_DUTYCYCLE_16_9
;
i2c
->
Init
.
GeneralCallMode
=
I2C_GENERALCALL_DISABLED
;
i2c
->
Init
.
NoStretchMode
=
I2C_NOSTRETCH_DISABLED
;
i2c
->
Init
.
OwnAddress1
=
0xfe
;
// unused
i2c
->
Init
.
OwnAddress2
=
0xfe
;
// unused
if
(
HAL_I2C_Init
(
i2c
)
!=
HAL_OK
)
{
// init error
// TODO should raise an exception, but this function is not necessarily going to be
...
...
@@ -83,6 +78,22 @@ void i2c_init(I2C_HandleTypeDef *i2c) {
}
}
void
i2c_deinit
(
I2C_HandleTypeDef
*
i2c
)
{
HAL_I2C_DeInit
(
i2c
);
if
(
0
)
{
#if MICROPY_HW_ENABLE_I2C1
}
else
if
(
i2c
->
Instance
==
I2C1
)
{
__I2C1_FORCE_RESET
();
__I2C1_RELEASE_RESET
();
__I2C1_CLK_DISABLE
();
#endif
}
else
if
(
i2c
->
Instance
==
I2C2
)
{
__I2C2_FORCE_RESET
();
__I2C2_RELEASE_RESET
();
__I2C2_CLK_DISABLE
();
}
}
/******************************************************************************/
/* Micro Python bindings */
...
...
@@ -91,6 +102,8 @@ typedef struct _pyb_i2c_obj_t {
I2C_HandleTypeDef
*
i2c
;
}
pyb_i2c_obj_t
;
STATIC
inline
bool
in_master_mode
(
pyb_i2c_obj_t
*
self
)
{
return
self
->
i2c
->
Init
.
OwnAddress1
==
PYB_I2C_MASTER_ADDRESS
;
}
STATIC
const
pyb_i2c_obj_t
pyb_i2c_obj
[]
=
{
#if MICROPY_HW_ENABLE_I2C1
{{
&
pyb_i2c_type
},
&
I2CHandle1
},
...
...
@@ -101,9 +114,64 @@ STATIC const pyb_i2c_obj_t pyb_i2c_obj[] = {
};
#define PYB_NUM_I2C (sizeof(pyb_i2c_obj) / sizeof(pyb_i2c_obj[0]))
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
;
uint
i2c_num
;
if
(
self
->
i2c
->
Instance
==
I2C1
)
{
i2c_num
=
1
;
}
else
{
i2c_num
=
2
;
}
if
(
self
->
i2c
->
State
==
HAL_I2C_STATE_RESET
)
{
print
(
env
,
"I2C(%u)"
,
i2c_num
);
}
else
{
if
(
in_master_mode
(
self
))
{
print
(
env
,
"I2C(%u, I2C.MASTER, baudrate=%u)"
,
i2c_num
,
self
->
i2c
->
Init
.
ClockSpeed
);
}
else
{
print
(
env
,
"I2C(%u, I2C.SLAVE, addr=0x%02x)"
,
i2c_num
,
(
self
->
i2c
->
Instance
->
OAR1
>>
1
)
&
0x7f
);
}
}
}
STATIC
const
mp_arg_parse_t
pyb_i2c_init_accepted_args
[]
=
{
{
MP_QSTR_mode
,
MP_ARG_PARSE_REQUIRED
|
MP_ARG_PARSE_INT
,
{.
u_int
=
0
}
},
{
MP_QSTR_addr
,
MP_ARG_PARSE_KW_ONLY
|
MP_ARG_PARSE_INT
,
{.
u_int
=
0x12
}
},
{
MP_QSTR_baudrate
,
MP_ARG_PARSE_KW_ONLY
|
MP_ARG_PARSE_INT
,
{.
u_int
=
400000
}
},
{
MP_QSTR_gencall
,
MP_ARG_PARSE_KW_ONLY
|
MP_ARG_PARSE_BOOL
,
{.
u_bool
=
false
}
},
};
#define PYB_I2C_INIT_NUM_ARGS (sizeof(pyb_i2c_init_accepted_args) / sizeof(pyb_i2c_init_accepted_args[0]))
STATIC
mp_obj_t
pyb_i2c_init_helper
(
const
pyb_i2c_obj_t
*
self
,
uint
n_args
,
const
mp_obj_t
*
args
,
mp_map_t
*
kw_args
)
{
// parse args
mp_arg_parse_val_t
vals
[
PYB_I2C_INIT_NUM_ARGS
];
mp_arg_parse_all
(
n_args
,
args
,
kw_args
,
PYB_I2C_INIT_NUM_ARGS
,
pyb_i2c_init_accepted_args
,
vals
);
// set the I2C configuration values
I2C_InitTypeDef
*
init
=
&
self
->
i2c
->
Init
;
if
(
vals
[
0
].
u_int
==
PYB_I2C_MASTER
)
{
// use a special address to indicate we are a master
init
->
OwnAddress1
=
PYB_I2C_MASTER_ADDRESS
;
}
else
{
init
->
OwnAddress1
=
(
vals
[
1
].
u_int
<<
1
)
&
0xfe
;
}
init
->
AddressingMode
=
I2C_ADDRESSINGMODE_7BIT
;
init
->
ClockSpeed
=
MIN
(
vals
[
2
].
u_int
,
400000
);
init
->
DualAddressMode
=
I2C_DUALADDRESS_DISABLED
;
init
->
DutyCycle
=
I2C_DUTYCYCLE_16_9
;
init
->
GeneralCallMode
=
vals
[
3
].
u_bool
?
I2C_GENERALCALL_ENABLED
:
I2C_GENERALCALL_DISABLED
;
init
->
NoStretchMode
=
I2C_NOSTRETCH_DISABLED
;
init
->
OwnAddress2
=
0xfe
;
// unused
// init the I2C bus
i2c_init
(
self
->
i2c
);
return
mp_const_none
;
}
STATIC
mp_obj_t
pyb_i2c_make_new
(
mp_obj_t
type_in
,
uint
n_args
,
uint
n_kw
,
const
mp_obj_t
*
args
)
{
// check arguments
mp_arg_check_num
(
n_args
,
n_kw
,
1
,
1
,
fals
e
);
mp_arg_check_num
(
n_args
,
n_kw
,
1
,
MP_OBJ_FUN_ARGS_MAX
,
tru
e
);
// get i2c number
machine_int_t
i2c_id
=
mp_obj_get_int
(
args
[
0
])
-
1
;
...
...
@@ -113,18 +181,39 @@ STATIC mp_obj_t pyb_i2c_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const
nlr_raise
(
mp_obj_new_exception_msg_varg
(
&
mp_type_ValueError
,
"I2C bus %d does not exist"
,
i2c_id
+
1
));
}
// get
i2c
object
// get
I2C
object
const
pyb_i2c_obj_t
*
i2c_obj
=
&
pyb_i2c_obj
[
i2c_id
];
if
(
n_args
>
1
||
n_kw
>
0
)
{
// start the peripheral
i2c_init
(
i2c_obj
->
i2c
);
mp_map_t
kw_args
;
mp_map_init_fixed_table
(
&
kw_args
,
n_kw
,
args
+
n_args
);
pyb_i2c_init_helper
(
i2c_obj
,
n_args
-
1
,
args
+
1
,
&
kw_args
);
}
return
(
mp_obj_t
)
i2c_obj
;
}
STATIC
mp_obj_t
pyb_i2c_init
(
uint
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
);
STATIC
mp_obj_t
pyb_i2c_deinit
(
mp_obj_t
self_in
)
{
pyb_i2c_obj_t
*
self
=
self_in
;
i2c_deinit
(
self
->
i2c
);
return
mp_const_none
;
}
STATIC
MP_DEFINE_CONST_FUN_OBJ_1
(
pyb_i2c_deinit_obj
,
pyb_i2c_deinit
);
// Check if an I2C device responds to the given address.
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
(
!
in_master_mode
(
self
))
{
nlr_raise
(
mp_obj_new_exception_msg
(
&
mp_type_TypeError
,
"I2C must be a master"
));
}
machine_uint_t
i2c_addr
=
mp_obj_get_int
(
i2c_addr_o
)
<<
1
;
for
(
int
i
=
0
;
i
<
10
;
i
++
)
{
...
...
@@ -136,13 +225,16 @@ STATIC mp_obj_t pyb_i2c_is_ready(mp_obj_t self_in, mp_obj_t i2c_addr_o) {
return
mp_const_false
;
}
STATIC
MP_DEFINE_CONST_FUN_OBJ_2
(
pyb_i2c_is_ready_obj
,
pyb_i2c_is_ready
);
// Scan all I2C addresses from 0x01 to 0x7f and return a list of those that respond.
STATIC
mp_obj_t
pyb_i2c_scan
(
mp_obj_t
self_in
)
{
pyb_i2c_obj_t
*
self
=
self_in
;
if
(
!
in_master_mode
(
self
))
{
nlr_raise
(
mp_obj_new_exception_msg
(
&
mp_type_TypeError
,
"I2C must be a master"
));
}
mp_obj_t
list
=
mp_obj_new_list
(
0
,
NULL
);
for
(
uint
addr
=
1
;
addr
<=
127
;
addr
++
)
{
...
...
@@ -157,88 +249,156 @@ STATIC mp_obj_t pyb_i2c_scan(mp_obj_t self_in) {
return
list
;
}
STATIC
MP_DEFINE_CONST_FUN_OBJ_1
(
pyb_i2c_scan_obj
,
pyb_i2c_scan
);
STATIC
mp_obj_t
pyb_i2c_read
(
mp_obj_t
self_in
,
mp_obj_t
i2c_addr_in
,
mp_obj_t
n_in
)
{
pyb_i2c_obj_t
*
self
=
self_in
;
machine_uint_t
i2c_addr
=
mp_obj_get_int
(
i2c_addr_in
)
<<
1
;
machine_uint_t
n
=
mp_obj_get_int
(
n_in
);
STATIC
const
mp_arg_parse_t
pyb_i2c_send_accepted_args
[]
=
{
{
MP_QSTR_send
,
MP_ARG_PARSE_REQUIRED
|
MP_ARG_PARSE_OBJ
,
{.
u_obj
=
MP_OBJ_NULL
}
},
{
MP_QSTR_addr
,
MP_ARG_PARSE_INT
,
{.
u_int
=
PYB_I2C_MASTER_ADDRESS
}
},
{
MP_QSTR_timeout
,
MP_ARG_PARSE_KW_ONLY
|
MP_ARG_PARSE_INT
,
{.
u_int
=
5000
}
},
};
#define PYB_I2C_SEND_NUM_ARGS (sizeof(pyb_i2c_send_accepted_args) / sizeof(pyb_i2c_send_accepted_args[0]))
STATIC
mp_obj_t
pyb_i2c_send
(
uint
n_args
,
const
mp_obj_t
*
args
,
mp_map_t
*
kw_args
)
{
pyb_i2c_obj_t
*
self
=
args
[
0
];
// parse args
mp_arg_parse_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_accepted_args
,
vals
);
byte
*
data
;
mp_obj_t
o
=
mp_obj_str_builder_start
(
&
mp_type_bytes
,
n
,
&
data
);
HAL_StatusTypeDef
status
=
HAL_I2C_Master_Receive
(
self
->
i2c
,
i2c_addr
,
data
,
n
,
500
);
// get the buffer to send from
mp_buffer_info_t
bufinfo
;
uint8_t
data
[
1
];
pyb_buf_get_for_send
(
vals
[
0
].
u_obj
,
&
bufinfo
,
data
);
// send the data
HAL_StatusTypeDef
status
;
if
(
in_master_mode
(
self
))
{
if
(
vals
[
1
].
u_int
==
PYB_I2C_MASTER_ADDRESS
)
{
nlr_raise
(
mp_obj_new_exception_msg
(
&
mp_type_TypeError
,
"addr argument required"
));
}
machine_uint_t
i2c_addr
=
vals
[
1
].
u_int
<<
1
;
status
=
HAL_I2C_Master_Transmit
(
self
->
i2c
,
i2c_addr
,
bufinfo
.
buf
,
bufinfo
.
len
,
vals
[
2
].
u_int
);
}
else
{
status
=
HAL_I2C_Slave_Transmit
(
self
->
i2c
,
bufinfo
.
buf
,
bufinfo
.
len
,
vals
[
2
].
u_int
);
}
if
(
status
!=
HAL_OK
)
{
// TODO really need a HardwareError object, or something
nlr_raise
(
mp_obj_new_exception_msg_varg
(
&
mp_type_Exception
,
"HAL_I2C_
Master_Receive
failed with code %d"
,
status
));
nlr_raise
(
mp_obj_new_exception_msg_varg
(
&
mp_type_Exception
,
"HAL_I2C_
xxx_Transmit
failed with code %d"
,
status
));
}
return
mp_
obj_str_builder_end
(
o
)
;
return
mp_
const_none
;
}
STATIC
MP_DEFINE_CONST_FUN_OBJ_KW
(
pyb_i2c_send_obj
,
1
,
pyb_i2c_send
);
STATIC
MP_DEFINE_CONST_FUN_OBJ_3
(
pyb_i2c_read_obj
,
pyb_i2c_read
);
STATIC
const
mp_arg_parse_t
pyb_i2c_recv_accepted_args
[]
=
{
{
MP_QSTR_recv
,
MP_ARG_PARSE_REQUIRED
|
MP_ARG_PARSE_OBJ
,
{.
u_obj
=
MP_OBJ_NULL
}
},
{
MP_QSTR_addr
,
MP_ARG_PARSE_INT
,
{.
u_int
=
PYB_I2C_MASTER_ADDRESS
}
},
{
MP_QSTR_timeout
,
MP_ARG_PARSE_KW_ONLY
|
MP_ARG_PARSE_INT
,
{.
u_int
=
5000
}
},
};
#define PYB_I2C_RECV_NUM_ARGS (sizeof(pyb_i2c_recv_accepted_args) / sizeof(pyb_i2c_recv_accepted_args[0]))
STATIC
mp_obj_t
pyb_i2c_write
(
mp_obj_t
self_in
,
mp_obj_t
i2c_addr_in
,
mp_obj_t
data_in
)
{
pyb_i2c_obj_t
*
self
=
self_in
;
machine_uint_t
i2c_addr
=
mp_obj_get_int
(
i2c_addr_in
)
<<
1
;
STATIC
mp_obj_t
pyb_i2c_recv
(
uint
n_args
,
const
mp_obj_t
*
args
,
mp_map_t
*
kw_args
)
{
pyb_i2c_obj_t
*
self
=
args
[
0
];
// parse args
mp_arg_parse_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_accepted_args
,
vals
);
// get the buffer to receive into
mp_buffer_info_t
bufinfo
;
mp_obj_t
o_ret
=
pyb_buf_get_for_recv
(
vals
[
0
].
u_obj
,
&
bufinfo
);
// receive the data
HAL_StatusTypeDef
status
;
if
(
MP_OBJ_IS_INT
(
data_in
))
{
uint8_t
data
[
1
]
=
{
mp_obj_get_int
(
data_in
)};
status
=
HAL_I2C_Master_Transmit
(
self
->
i2c
,
i2c_addr
,
data
,
1
,
500
);
if
(
in_master_mode
(
self
))
{
if
(
vals
[
1
].
u_int
==
PYB_I2C_MASTER_ADDRESS
)
{
nlr_raise
(
mp_obj_new_exception_msg
(
&
mp_type_TypeError
,
"addr argument required"
));
}
machine_uint_t
i2c_addr
=
vals
[
1
].
u_int
<<
1
;
status
=
HAL_I2C_Master_Receive
(
self
->
i2c
,
i2c_addr
,
bufinfo
.
buf
,
bufinfo
.
len
,
vals
[
2
].
u_int
);
}
else
{
mp_buffer_info_t
bufinfo
;
mp_get_buffer_raise
(
data_in
,
&
bufinfo
,
MP_BUFFER_READ
);
status
=
HAL_I2C_Master_Transmit
(
self
->
i2c
,
i2c_addr
,
bufinfo
.
buf
,
bufinfo
.
len
,
500
);
status
=
HAL_I2C_Slave_Receive
(
self
->
i2c
,
bufinfo
.
buf
,
bufinfo
.
len
,
vals
[
2
].
u_int
);
}
if
(
status
!=
HAL_OK
)
{
// TODO really need a HardwareError object, or something
nlr_raise
(
mp_obj_new_exception_msg_varg
(
&
mp_type_Exception
,
"HAL_I2C_
Master_Transmit
failed with code %d"
,
status
));
nlr_raise
(
mp_obj_new_exception_msg_varg
(
&
mp_type_Exception
,
"HAL_I2C_
xxx_Receive
failed with code %d"
,
status
));
}
return
mp_const_none
;
// return the received data
if
(
o_ret
==
MP_OBJ_NULL
)
{
return
vals
[
0
].
u_obj
;
}
else
{
return
mp_obj_str_builder_end
(
o_ret
);
}
}
STATIC
MP_DEFINE_CONST_FUN_OBJ_KW
(
pyb_i2c_recv_obj
,
1
,
pyb_i2c_recv
);
STATIC
MP_DEFINE_CONST_FUN_OBJ_3
(
pyb_i2c_write_obj
,
pyb_i2c_write
);
STATIC
const
mp_arg_parse_t
pyb_i2c_mem_read_accepted_args
[]
=
{
{
MP_QSTR_data
,
MP_ARG_PARSE_REQUIRED
|
MP_ARG_PARSE_OBJ
,
{.
u_obj
=
MP_OBJ_NULL
}
},
{
MP_QSTR_addr
,
MP_ARG_PARSE_REQUIRED
|
MP_ARG_PARSE_INT
,
{.
u_int
=
0
}
},
{
MP_QSTR_memaddr
,
MP_ARG_PARSE_REQUIRED
|
MP_ARG_PARSE_INT
,
{.
u_int
=
0
}
},
{
MP_QSTR_timeout
,
MP_ARG_PARSE_KW_ONLY
|
MP_ARG_PARSE_INT
,
{.
u_int
=
5000
}
},
};
#define PYB_I2C_MEM_READ_NUM_ARGS (sizeof(pyb_i2c_mem_read_accepted_args) / sizeof(pyb_i2c_mem_read_accepted_args[0]))
STATIC
mp_obj_t
pyb_i2c_mem_read
(
uint
n_args
,
const
mp_obj_t
*
args
)
{
STATIC
mp_obj_t
pyb_i2c_mem_read
(
uint
n_args
,
const
mp_obj_t
*
args
,
mp_map_t
*
kw_args
)
{
pyb_i2c_obj_t
*
self
=
args
[
0
];
machine_uint_t
i2c_addr
=
mp_obj_get_int
(
args
[
1
])
<<
1
;
machine_uint_t
mem_addr
=
mp_obj_get_int
(
args
[
2
]);
machine_uint_t
n
=
mp_obj_get_int
(
args
[
3
]);
byte
*
data
;
mp_obj_t
o
=
mp_obj_str_builder_start
(
&
mp_type_bytes
,
n
,
&
data
);
HAL_StatusTypeDef
status
=
HAL_I2C_Mem_Read
(
self
->
i2c
,
i2c_addr
,
mem_addr
,
I2C_MEMADD_SIZE_8BIT
,
data
,
n
,
200
);
if
(
!
in_master_mode
(
self
))
{
nlr_raise
(
mp_obj_new_exception_msg
(
&
mp_type_TypeError
,
"I2C must be a master"
));
}
// parse args
mp_arg_parse_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_accepted_args
,
vals
);
//printf("Read got %d\n", status);
// get the buffer to read into
mp_buffer_info_t
bufinfo
;
mp_obj_t
o_ret
=
pyb_buf_get_for_recv
(
vals
[
0
].
u_obj
,
&
bufinfo
);
// get the addresses
machine_uint_t
i2c_addr
=
vals
[
1
].
u_int
<<
1
;
machine_uint_t
mem_addr
=
vals
[
2
].
u_int
;
HAL_StatusTypeDef
status
=
HAL_I2C_Mem_Read
(
self
->
i2c
,
i2c_addr
,
mem_addr
,
I2C_MEMADD_SIZE_8BIT
,
bufinfo
.
buf
,
bufinfo
.
len
,
vals
[
3
].
u_int
);
if
(
status
!=
HAL_OK
)
{
// TODO really need a HardwareError object, or something
nlr_raise
(
mp_obj_new_exception_msg_varg
(
&
mp_type_Exception
,
"HAL_I2C_Mem_Read failed with code %d"
,
status
));
}
return
mp_obj_str_builder_end
(
o
);
// return the read data
if
(
o_ret
==
MP_OBJ_NULL
)
{
return
vals
[
0
].
u_obj
;
}
else
{
return
mp_obj_str_builder_end
(
o_ret
);
}
}
STATIC
MP_DEFINE_CONST_FUN_OBJ_KW
(
pyb_i2c_mem_read_obj
,
1
,
pyb_i2c_mem_read
);
STATIC
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN
(
pyb_i2c_mem_read_obj
,
4
,
4
,
pyb_i2c_mem_read
);
STATIC
mp_obj_t
pyb_i2c_mem_write
(
uint
n_args
,
const
mp_obj_t
*
args
)
{
STATIC
mp_obj_t
pyb_i2c_mem_write
(
uint
n_args
,
const
mp_obj_t
*
args
,
mp_map_t
*
kw_args
)
{
pyb_i2c_obj_t
*
self
=
args
[
0
];
machine_uint_t
i2c_addr
=
mp_obj_get_int
(
args
[
1
])
<<
1
;
machine_uint_t
mem_addr
=
mp_obj_get_int
(
args
[
2
]);
HAL_StatusTypeDef
status
;
if
(
MP_OBJ_IS_INT
(
args
[
3
]))
{
uint8_t
data
[
1
]
=
{
mp_obj_get_int
(
args
[
3
])};
status
=
HAL_I2C_Mem_Write
(
self
->
i2c
,
i2c_addr
,
mem_addr
,
I2C_MEMADD_SIZE_8BIT
,
data
,
1
,
200
);
}
else
{
mp_buffer_info_t
bufinfo
;
mp_get_buffer_raise
(
args
[
3
],
&
bufinfo
,
MP_BUFFER_READ
);
status
=
HAL_I2C_Mem_Write
(
self
->
i2c
,
i2c_addr
,
mem_addr
,
I2C_MEMADD_SIZE_8BIT
,
bufinfo
.
buf
,
bufinfo
.
len
,
200
);
if
(
!
in_master_mode
(
self
))
{
nlr_raise
(
mp_obj_new_exception_msg
(
&
mp_type_TypeError
,
"I2C must be a master"
));
}
//printf("Write got %d\n", status);
// parse args (same as mem_read)
mp_arg_parse_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_accepted_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
machine_uint_t
i2c_addr
=
vals
[
1
].
u_int
<<
1
;
machine_uint_t
mem_addr
=
vals
[
2
].
u_int
;
HAL_StatusTypeDef
status
=
HAL_I2C_Mem_Write
(
self
->
i2c
,
i2c_addr
,
mem_addr
,
I2C_MEMADD_SIZE_8BIT
,
bufinfo
.
buf
,
bufinfo
.
len
,
vals
[
3
].
u_int
);
if
(
status
!=
HAL_OK
)
{
// TODO really need a HardwareError object, or something
...
...
@@ -247,16 +407,22 @@ STATIC mp_obj_t pyb_i2c_mem_write(uint n_args, const mp_obj_t *args) {
return
mp_const_none
;
}
STATIC
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN
(
pyb_i2c_mem_write_obj
,
4
,
4
,
pyb_i2c_mem_write
);
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_
rea
d
),
(
mp_obj_t
)
&
pyb_i2c_
rea
d_obj
},
{
MP_OBJ_NEW_QSTR
(
MP_QSTR_
write
),
(
mp_obj_t
)
&
pyb_i2c_
write
_obj
},
{
MP_OBJ_NEW_QSTR
(
MP_QSTR_
sen
d
),
(
mp_obj_t
)
&
pyb_i2c_
sen
d_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
{
MP_OBJ_NEW_QSTR
(
MP_QSTR_MASTER
),
MP_OBJ_NEW_SMALL_INT
(
PYB_I2C_MASTER
)
},
{
MP_OBJ_NEW_QSTR
(
MP_QSTR_SLAVE
),
MP_OBJ_NEW_SMALL_INT
(
PYB_I2C_SLAVE
)
},
};
STATIC
MP_DEFINE_CONST_DICT
(
pyb_i2c_locals_dict
,
pyb_i2c_locals_dict_table
);
...
...
@@ -264,6 +430,7 @@ 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
,
};
stmhal/i2c.h
View file @
eb8bdf4d
// use this for OwnAddress1 to configure I2C in master mode
#define PYB_I2C_MASTER_ADDRESS (0xfe)
extern
I2C_HandleTypeDef
I2CHandle1
;
extern
I2C_HandleTypeDef
I2CHandle2
;
extern
const
mp_obj_type_t
pyb_i2c_type
;
...
...
stmhal/qstrdefsport.h
View file @
eb8bdf4d
...
...
@@ -106,8 +106,19 @@ Q(EVT_RISING_FALLING)
// for I2C object
Q
(
I2C
)
Q
(
mode
)
Q
(
addr
)
Q
(
baudrate
)
Q
(
gencall
)
Q
(
data
)
Q
(
memaddr
)
Q
(
timeout
)
Q
(
init
)
Q
(
deinit
)
Q
(
is_ready
)
Q
(
scan
)
Q
(
send
)
Q
(
recv
)
Q
(
mem_read
)
Q
(
mem_write
)
...
...
@@ -120,16 +131,18 @@ Q(recv)
Q
(
send_recv
)
Q
(
mode
)
Q
(
baudrate
)
Q
(
clk
pol
)
Q
(
clk
phase
)
Q
(
pol
arity
)
Q
(
phase
)
Q
(
dir
)
Q
(
size
)
Q
(
nss
)
Q
(
firstbit
)
Q
(
ti
)
Q
(
crc
poly
)
Q
(
crc
)
Q
(
MASTER
)
Q
(
SLAVE
)
Q
(
MSB
)
Q
(
LSB
)
// for Accel object
Q
(
Accel
)
...
...
stmhal/spi.c
View file @
eb8bdf4d
...
...
@@ -11,6 +11,7 @@
#include
"runtime.h"
#include
"pin.h"
#include
"genhdr/pins.h"
#include
"bufhelper.h"
#include
"spi.h"
#if MICROPY_HW_ENABLE_SPI1
...
...
@@ -41,7 +42,7 @@ void spi_init(SPI_HandleTypeDef *spi) {
GPIO_InitTypeDef
GPIO_InitStructure
;
GPIO_InitStructure
.
Mode
=
GPIO_MODE_AF_PP
;
GPIO_InitStructure
.
Speed
=
GPIO_SPEED_FAST
;
GPIO_InitStructure
.
Pull
=
GPIO_PULLUP
;
// ST examples use
PULLUP
GPIO_InitStructure
.
Pull
=
spi
->
Init
.
CLKPolarity
==
SPI_POLARITY_LOW
?
GPIO_PULLDOWN
:
GPIO_
PULLUP
;
const
pin_obj_t
*
pins
[
4
];
if
(
0
)
{
...
...
@@ -100,12 +101,18 @@ void spi_deinit(SPI_HandleTypeDef *spi) {
if
(
0
)
{
#if MICROPY_HW_ENABLE_SPI1
}
else
if
(
spi
->
Instance
==
SPI1
)
{
__SPI1_FORCE_RESET
();
__SPI1_RELEASE_RESET
();
__SPI1_CLK_DISABLE
();
#endif
}
else
if
(
spi
->
Instance
==
SPI2
)
{
__SPI2_FORCE_RESET
();
__SPI2_RELEASE_RESET
();
__SPI2_CLK_DISABLE
();
#if MICROPY_HW_ENABLE_SPI3
}
else
if
(
spi
->
Instance
==
SPI3
)
{
__SPI3_FORCE_RESET
();
__SPI3_RELEASE_RESET
();
__SPI3_CLK_DISABLE
();
#endif
}
...
...
@@ -156,29 +163,34 @@ STATIC void pyb_spi_print(void (*print)(void *env, const char *fmt, ...), void *
spi_clock
=
HAL_RCC_GetPCLK1Freq
();
}
uint
baudrate
=
spi_clock
>>
((
self
->
spi
->
Init
.
BaudRatePrescaler
>>
3
)
+
1
);
print
(
env
,
"SPI(%u, SPI.MASTER,
clock=%u,
baudrate=%u
)
"
,
spi_num
,
spi_clock
,
baudrate
);
print
(
env
,
"SPI(%u, SPI.MASTER, baudrate=%u"
,
spi_num
,
baudrate
);
}
else
{
print
(
env
,
"SPI(%u, SPI.SLAVE
)
"
,
spi_num
);
print
(
env
,
"SPI(%u, SPI.SLAVE"
,
spi_num
);
}
print
(
env
,
", polarity=%u, phase=%u, size=%u"
,
self
->
spi
->
Init
.
CLKPolarity
==
SPI_POLARITY_LOW
?
0
:
1
,
self
->
spi
->
Init
.
CLKPhase
==
SPI_PHASE_1EDGE
?
1
:
2
,
self
->
spi
->
Init
.
DataSize
==
SPI_DATASIZE_8BIT
?
8
:
16
);
if
(
self
->
spi
->
Init
.
CRCCalculation
==
SPI_CRCCALCULATION_ENABLED
)
{
print
(
env
,
", crc=0x%x"
,
self
->
spi
->
Init
.
CRCPolynomial
);
}
print
(
env
,
")"
);
}
}
STATIC
const
mp_arg_parse_t
pyb_spi_init_accepted_args
[]
=
{
{
MP_QSTR_mode
,
MP_ARG_PARSE_REQUIRED
|
MP_ARG_PARSE_INT
,
{.
u_int
=
0
}
},
{
MP_QSTR_baudrate
,
MP_ARG_PARSE_INT
,
{.
u_int
=
328125
}
},
{
MP_QSTR_
clkpol
,
MP_ARG_PARSE_KW_ONLY
|
MP_ARG_PARSE_INT
,
{.
u_int
=
SPI_POLARITY_LOW
}
},
{
MP_QSTR_
clk
phase
,
MP_ARG_PARSE_KW_ONLY
|
MP_ARG_PARSE_INT
,
{.
u_int
=
SPI_PHASE_1EDGE
}
},
{
MP_QSTR_
polarity
,
MP_ARG_PARSE_KW_ONLY
|
MP_ARG_PARSE_INT
,
{.
u_int
=
1
}
},
{
MP_QSTR_phase
,
MP_ARG_PARSE_KW_ONLY
|
MP_ARG_PARSE_INT
,
{.
u_int
=
1
}
},
{
MP_QSTR_dir
,
MP_ARG_PARSE_KW_ONLY
|
MP_ARG_PARSE_INT
,
{.
u_int
=
SPI_DIRECTION_2LINES
}
},
{
MP_QSTR_size
,
MP_ARG_PARSE_KW_ONLY
|
MP_ARG_PARSE_INT
,
{.
u_int
=
8
}
},
{
MP_QSTR_nss
,
MP_ARG_PARSE_KW_ONLY
|
MP_ARG_PARSE_INT
,
{.
u_int
=
SPI_NSS_SOFT
}
},
{
MP_QSTR_firstbit
,
MP_ARG_PARSE_KW_ONLY
|
MP_ARG_PARSE_INT
,
{.
u_int
=
SPI_FIRSTBIT_MSB
}
},
{
MP_QSTR_ti
,
MP_ARG_PARSE_KW_ONLY
|
MP_ARG_PARSE_BOOL
,
{.
u_bool
=
false
}
},
{
MP_QSTR_crc
poly
,
MP_ARG_PARSE_KW_ONLY
|
MP_ARG_PARSE_OBJ
,
{.
u_obj
=
mp_const_none
}
},
{
MP_QSTR_crc
,
MP_ARG_PARSE_KW_ONLY
|
MP_ARG_PARSE_OBJ
,
{.
u_obj
=
mp_const_none
}
},
};
#define PYB_SPI_INIT_NUM_ARGS (sizeof(pyb_spi_init_accepted_args) / sizeof(pyb_spi_init_accepted_args[0]))
STATIC
mp_obj_t
pyb_spi_init_helper
(
const
pyb_spi_obj_t
*
self
,
uint
n_args
,
const
mp_obj_t
*
args
,
mp_map_t
*
kw_args
)
{
// parse
keyword
args
// parse args
mp_arg_parse_val_t
vals
[
PYB_SPI_INIT_NUM_ARGS
];
mp_arg_parse_all
(
n_args
,
args
,
kw_args
,
PYB_SPI_INIT_NUM_ARGS
,
pyb_spi_init_accepted_args
,
vals
);
...
...
@@ -206,8 +218,8 @@ STATIC mp_obj_t pyb_spi_init_helper(const pyb_spi_obj_t *self, uint n_args, cons
else
if
(
br_prescale
<=
128
)
{
init
->
BaudRatePrescaler
=
SPI_BAUDRATEPRESCALER_128
;
}
else
{
init
->
BaudRatePrescaler
=
SPI_BAUDRATEPRESCALER_256
;
}
init
->
CLKPolarity
=
vals
[
2
].
u_int
;
init
->
CLKPhase
=
vals
[
3
].
u_int
;