Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
TASTE
uPython-mirror
Commits
6474598c
Commit
6474598c
authored
Dec 28, 2013
by
Hagen Kaye
Browse files
Added i2c python interface object
parent
b8ecc29f
Changes
2
Hide whitespace changes
Inline
Side-by-side
stm/i2c.c
0 → 100644
View file @
6474598c
#include <stdio.h>
#include <stm32f4xx.h>
#include <stm32f4xx_rcc.h>
#include <stm32f4xx_gpio.h>
#include "misc.h"
#include "systick.h"
#include "mpconfig.h"
#include "obj.h"
typedef
enum
{
PYB_I2C_1
=
0
,
PYB_I2C_2
=
1
,
}
pyb_i2c_t
;
typedef
enum
{
I2C_STATE_IDLE
=
0
,
I2C_STATE_WRITE
=
1
,
I2C_STATE_READ
=
2
,
}
i2c_state_t
;
// set to true if the port has already been initialized
bool
i2c1_port_initialized
=
false
;
bool
i2c2_port_initialized
=
false
;
static
I2C_TypeDef
*
_i2c_port_addr
(
pyb_i2c_t
i2c_port
)
{
if
(
i2c_port
==
PYB_I2C_1
)
return
I2C1
;
if
(
i2c_port
==
PYB_I2C_2
)
return
I2C2
;
return
NULL
;
}
// todo - perhaps there should be some global resource management for gpio
// this function would fail if the i2c pins have already been defined for
// use by another python object
// as it is, this always returns true (unless i2c_port is invalid)
static
bool
_i2c_init
(
pyb_i2c_t
i2c_port
)
{
GPIO_InitTypeDef
GPIO_InitStructure
;
I2C_TypeDef
*
i2c
=
_i2c_port_addr
(
i2c_port
);
if
(
i2c
==
NULL
)
return
false
;
if
(
i2c_port
==
PYB_I2C_1
)
{
if
(
i2c1_port_initialized
==
true
)
return
true
;
RCC
->
APB1ENR
|=
RCC_APB1ENR_I2C1EN
;
// enable I2C1
// PB6=SCL, PB7=SDA
GPIO_InitStructure
.
GPIO_Pin
=
GPIO_Pin_6
|
GPIO_Pin_7
;
GPIO_InitStructure
.
GPIO_Mode
=
GPIO_Mode_AF
;
GPIO_InitStructure
.
GPIO_OType
=
GPIO_OType_OD
;
GPIO_InitStructure
.
GPIO_Speed
=
GPIO_Speed_25MHz
;
GPIO_InitStructure
.
GPIO_PuPd
=
GPIO_PuPd_NOPULL
;
GPIO_Init
(
GPIOB
,
&
GPIO_InitStructure
);
// alternate functions for SCL and SDA
GPIO_PinAFConfig
(
GPIOB
,
GPIO_PinSource6
,
GPIO_AF_I2C1
);
GPIO_PinAFConfig
(
GPIOB
,
GPIO_PinSource7
,
GPIO_AF_I2C1
);
i2c1_port_initialized
=
true
;
}
if
(
i2c_port
==
PYB_I2C_2
)
{
if
(
i2c2_port_initialized
==
true
)
return
true
;
RCC
->
APB1ENR
|=
RCC_APB1ENR_I2C2EN
;
// enable I2C2
// PB10=SCL, PB11=SDA
GPIO_InitStructure
.
GPIO_Pin
=
GPIO_Pin_10
|
GPIO_Pin_11
;
GPIO_InitStructure
.
GPIO_Mode
=
GPIO_Mode_AF
;
GPIO_InitStructure
.
GPIO_OType
=
GPIO_OType_OD
;
GPIO_InitStructure
.
GPIO_Speed
=
GPIO_Speed_25MHz
;
GPIO_InitStructure
.
GPIO_PuPd
=
GPIO_PuPd_NOPULL
;
GPIO_Init
(
GPIOB
,
&
GPIO_InitStructure
);
// alternate functions for SCL and SDA
GPIO_PinAFConfig
(
GPIOB
,
GPIO_PinSource10
,
GPIO_AF_I2C2
);
GPIO_PinAFConfig
(
GPIOB
,
GPIO_PinSource11
,
GPIO_AF_I2C2
);
i2c2_port_initialized
=
true
;
}
// get clock speeds
RCC_ClocksTypeDef
rcc_clocks
;
RCC_GetClocksFreq
(
&
rcc_clocks
);
// disable the I2C peripheral before we configure it
i2c
->
CR1
&=
~
I2C_CR1_PE
;
// program peripheral input clock
i2c
->
CR2
=
4
;
// no interrupts; 4 MHz (hopefully!) (could go up to 42MHz)
// configure clock control reg
uint32_t
freq
=
rcc_clocks
.
PCLK1_Frequency
/
(
100000
<<
1
);
// want 100kHz, this is the formula for freq
i2c
->
CCR
=
freq
;
// standard mode (speed), freq calculated as above
// configure rise time reg
i2c
->
TRISE
=
(
rcc_clocks
.
PCLK1_Frequency
/
1000000
)
+
1
;
// formula for trise, gives maximum rise time
// enable the I2C peripheral
i2c
->
CR1
|=
I2C_CR1_PE
;
return
true
;
}
static
uint32_t
_i2c_get_sr
(
pyb_i2c_t
i2c_port
)
{
// must read SR1 first, then SR2, as the read can clear some flags
I2C_TypeDef
*
i2c
=
_i2c_port_addr
(
i2c_port
);
if
(
i2c
==
NULL
)
return
0
;
uint32_t
sr1
=
i2c
->
SR1
;
uint32_t
sr2
=
i2c
->
SR2
;
return
(
sr2
<<
16
)
|
sr1
;
}
static
bool
_i2c_restart
(
pyb_i2c_t
i2c_port
,
uint8_t
addr
,
int
write
)
{
I2C_TypeDef
*
i2c
=
_i2c_port_addr
(
i2c_port
);
if
(
i2c
==
NULL
)
return
false
;
// send start condition
i2c
->
CR1
|=
I2C_CR1_START
;
// wait for BUSY, MSL and SB --> Slave has acknowledged start condition
uint32_t
timeout
=
1000000
;
while
((
_i2c_get_sr
(
i2c_port
)
&
0x00030001
)
!=
0x00030001
)
{
if
(
--
timeout
==
0
)
{
//printf("timeout in _i2c_restart\n");
return
false
;
}
}
if
(
write
)
{
// send address and write bit
i2c
->
DR
=
(
addr
<<
1
)
|
0
;
// wait for BUSY, MSL, ADDR, TXE and TRA
timeout
=
1000000
;
while
((
_i2c_get_sr
(
i2c_port
)
&
0x00070082
)
!=
0x00070082
)
{
if
(
--
timeout
==
0
)
{
//printf("timeout in _i2c_restart write\n");
return
false
;
}
}
}
else
{
// send address and read bit
i2c
->
DR
=
(
addr
<<
1
)
|
1
;
// wait for BUSY, MSL and ADDR flags
timeout
=
1000000
;
while
((
_i2c_get_sr
(
i2c_port
)
&
0x00030002
)
!=
0x00030002
)
{
if
(
--
timeout
==
0
)
{
//printf("timeout in _i2c_restart read\n");
return
false
;
}
}
}
return
true
;
}
static
bool
_i2c_send_byte
(
pyb_i2c_t
i2c_port
,
uint8_t
data
)
{
I2C_TypeDef
*
i2c
=
_i2c_port_addr
(
i2c_port
);
if
(
i2c
==
NULL
)
return
false
;
// send byte
i2c
->
DR
=
data
;
// wait for TRA, BUSY, MSL, TXE and BTF (byte transmitted)
uint32_t
timeout
=
1000000
;
while
((
_i2c_get_sr
(
i2c_port
)
&
0x00070084
)
!=
0x00070084
)
{
if
(
--
timeout
==
0
)
{
//printf("timeout in _i2c_send_byte\n");
return
false
;
}
}
return
true
;
}
static
uint8_t
_i2c_read_ack
(
pyb_i2c_t
i2c_port
)
{
I2C_TypeDef
*
i2c
=
_i2c_port_addr
(
i2c_port
);
if
(
i2c
==
NULL
)
return
0
;
// enable ACK of received byte
i2c
->
CR1
|=
I2C_CR1_ACK
;
// wait for BUSY, MSL and RXNE (byte received)
uint32_t
timeout
=
1000000
;
while
((
_i2c_get_sr
(
i2c_port
)
&
0x00030040
)
!=
0x00030040
)
{
if
(
--
timeout
==
0
)
{
//printf("timeout in _i2c_read_ack\n");
break
;
}
}
// read and return data
uint8_t
data
=
i2c
->
DR
;
return
data
;
}
static
uint8_t
_i2c_read_nack
(
pyb_i2c_t
i2c_port
)
{
I2C_TypeDef
*
i2c
=
_i2c_port_addr
(
i2c_port
);
if
(
i2c
==
NULL
)
return
0
;
// disable ACK of received byte (to indicate end of receiving)
i2c
->
CR1
&=
(
uint16_t
)
~
((
uint16_t
)
I2C_CR1_ACK
);
// last byte should apparently also generate a stop condition
i2c
->
CR1
|=
I2C_CR1_STOP
;
// wait for BUSY, MSL and RXNE (byte received)
uint32_t
timeout
=
1000000
;
while
((
_i2c_get_sr
(
i2c_port
)
&
0x00030040
)
!=
0x00030040
)
{
if
(
--
timeout
==
0
)
{
//printf("timeout in _i2c_read_nack\n");
break
;
}
}
// read and return data
uint8_t
data
=
i2c
->
DR
;
return
data
;
}
static
bool
_i2c_start
(
pyb_i2c_t
i2c_port
)
{
I2C_TypeDef
*
i2c
=
_i2c_port_addr
(
i2c_port
);
if
(
i2c
==
NULL
)
return
false
;
// wait until I2C is not busy
uint32_t
timeout
=
1000000
;
while
(
i2c
->
SR2
&
I2C_SR2_BUSY
)
{
if
(
--
timeout
==
0
)
{
return
false
;
}
}
return
true
;
}
static
void
_i2c_stop
(
pyb_i2c_t
i2c_port
)
{
I2C_TypeDef
*
i2c
=
_i2c_port_addr
(
i2c_port
);
if
(
i2c
==
NULL
)
return
;
// send stop condition
i2c
->
CR1
|=
I2C_CR1_STOP
;
}
/******************************************************************************/
/* Micro Python bindings */
typedef
struct
_pyb_i2c_obj_t
{
mp_obj_base_t
base
;
pyb_i2c_t
i2c_port
;
int
i2c_addr
;
i2c_state_t
i2c_state
;
}
pyb_i2c_obj_t
;
void
i2c_obj_print
(
void
(
*
print
)(
void
*
env
,
const
char
*
fmt
,
...),
void
*
env
,
mp_obj_t
self_in
)
{
pyb_i2c_obj_t
*
self
=
self_in
;
print
(
env
,
"<I2C%lu addr:%lu>"
,
(
unsigned
int
)
self
->
i2c_port
,
(
unsigned
int
)
self
->
i2c_addr
);
}
// calls _i2c_start with write=0,1 depending on LSB of i2c_addr
mp_obj_t
i2c_obj_start
(
mp_obj_t
self_in
)
{
pyb_i2c_obj_t
*
self
=
self_in
;
if
(
self
->
i2c_state
!=
I2C_STATE_IDLE
)
{
_i2c_stop
(
self
->
i2c_port
);
self
->
i2c_state
=
I2C_STATE_IDLE
;
}
if
(
_i2c_start
(
self
->
i2c_port
)
==
true
)
return
mp_const_true
;
return
mp_const_false
;
}
mp_obj_t
i2c_obj_write
(
mp_obj_t
self_in
,
mp_obj_t
data_in
)
{
pyb_i2c_obj_t
*
self
=
self_in
;
if
(
self
->
i2c_state
!=
I2C_STATE_WRITE
)
{
if
(
_i2c_restart
(
self
->
i2c_port
,
self
->
i2c_addr
,
1
)
==
false
)
{
_i2c_stop
(
self
->
i2c_port
);
self
->
i2c_state
=
I2C_STATE_IDLE
;
return
mp_const_false
;
}
self
->
i2c_state
=
I2C_STATE_WRITE
;
}
uint8_t
data
=
mp_obj_get_int
(
data_in
);
if
(
_i2c_send_byte
(
self
->
i2c_port
,
data
)
==
false
)
return
mp_const_false
;
return
mp_const_true
;
}
mp_obj_t
i2c_obj_read
(
mp_obj_t
self_in
)
{
pyb_i2c_obj_t
*
self
=
self_in
;
if
(
self
->
i2c_state
!=
I2C_STATE_READ
)
{
if
(
_i2c_restart
(
self
->
i2c_port
,
self
->
i2c_addr
,
0
)
==
false
)
{
_i2c_stop
(
self
->
i2c_port
);
self
->
i2c_state
=
I2C_STATE_IDLE
;
return
mp_const_false
;
}
self
->
i2c_state
=
I2C_STATE_READ
;
}
uint8_t
data
=
_i2c_read_ack
(
self
->
i2c_port
);
return
mp_obj_new_int
(
data
);
}
mp_obj_t
i2c_obj_readAndStop
(
mp_obj_t
self_in
)
{
pyb_i2c_obj_t
*
self
=
self_in
;
if
(
self
->
i2c_state
!=
I2C_STATE_READ
)
{
if
(
_i2c_restart
(
self
->
i2c_port
,
self
->
i2c_addr
,
0
)
==
false
)
{
_i2c_stop
(
self
->
i2c_port
);
self
->
i2c_state
=
I2C_STATE_IDLE
;
return
mp_const_false
;
}
}
uint8_t
data
=
_i2c_read_nack
(
self
->
i2c_port
);
self
->
i2c_state
=
I2C_STATE_IDLE
;
return
mp_obj_new_int
(
data
);
}
mp_obj_t
i2c_obj_stop
(
mp_obj_t
self_in
)
{
pyb_i2c_obj_t
*
self
=
self_in
;
_i2c_stop
(
self
->
i2c_port
);
self
->
i2c_state
=
I2C_STATE_IDLE
;
return
mp_const_none
;
}
static
MP_DEFINE_CONST_FUN_OBJ_1
(
i2c_obj_start_obj
,
i2c_obj_start
);
static
MP_DEFINE_CONST_FUN_OBJ_2
(
i2c_obj_write_obj
,
i2c_obj_write
);
static
MP_DEFINE_CONST_FUN_OBJ_1
(
i2c_obj_read_obj
,
i2c_obj_read
);
static
MP_DEFINE_CONST_FUN_OBJ_1
(
i2c_obj_readAndStop_obj
,
i2c_obj_readAndStop
);
static
MP_DEFINE_CONST_FUN_OBJ_1
(
i2c_obj_stop_obj
,
i2c_obj_stop
);
static
const
mp_obj_type_t
i2c_obj_type
=
{
{
&
mp_const_type
},
"I2C"
,
i2c_obj_print
,
// print
NULL
,
// call_n
NULL
,
// unary_op
NULL
,
// binary_op
NULL
,
// getiter
NULL
,
// iternext
{
// method list
{
"start"
,
&
i2c_obj_start_obj
},
{
"write"
,
&
i2c_obj_write_obj
},
{
"read"
,
&
i2c_obj_read_obj
},
{
"readAndStop"
,
&
i2c_obj_readAndStop_obj
},
{
"stop"
,
&
i2c_obj_stop_obj
},
{
NULL
,
NULL
},
}
};
// create the I2C object
// currently support either I2C1 (i2c_id = 0) or I2C2 (i2c_id = 1)
mp_obj_t
pyb_I2C
(
mp_obj_t
i2c_id
,
mp_obj_t
i2c_addr
)
{
pyb_i2c_t
i2c_port
;
switch
(
mp_obj_get_int
(
i2c_id
))
{
case
0
:
i2c_port
=
PYB_I2C_1
;
break
;
case
1
:
i2c_port
=
PYB_I2C_2
;
break
;
default:
return
mp_const_none
;
}
if
(
_i2c_init
(
i2c_port
)
==
false
)
return
mp_const_none
;
pyb_i2c_obj_t
*
o
=
m_new_obj
(
pyb_i2c_obj_t
);
o
->
base
.
type
=
&
i2c_obj_type
;
o
->
i2c_port
=
i2c_port
;
o
->
i2c_addr
=
mp_obj_get_int
(
i2c_addr
);
o
->
i2c_state
=
I2C_STATE_IDLE
;
return
o
;
}
stm/i2c.h
0 → 100644
View file @
6474598c
mp_obj_t
pyb_I2C
(
mp_obj_t
i2c_id
,
mp_obj_t
i2c_addr
);
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment