Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
tools-mirror
Micropython
提交
19778d0a
M
Micropython
项目概览
tools-mirror
/
Micropython
12 个月 前同步成功
通知
0
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
M
Micropython
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
19778d0a
编写于
4月 24, 2018
作者:
D
Damien George
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
stm32/i2c: Add low-level I2C driver for F7 MCUs.
上级
0c54d0c2
变更
3
显示空白变更内容
内联
并排
Showing
3 changed file
with
244 addition
and
0 deletion
+244
-0
ports/stm32/Makefile
ports/stm32/Makefile
+1
-0
ports/stm32/i2c.c
ports/stm32/i2c.c
+234
-0
ports/stm32/i2c.h
ports/stm32/i2c.h
+9
-0
未找到文件。
ports/stm32/Makefile
浏览文件 @
19778d0a
...
...
@@ -216,6 +216,7 @@ SRC_C = \
pin_named_pins.c
\
bufhelper.c
\
dma.c
\
i2c.c
\
pyb_i2c.c
\
spi.c
\
qspi.c
\
...
...
ports/stm32/i2c.c
0 → 100644
浏览文件 @
19778d0a
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2018 Damien P. George
*
* 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 "py/mperrno.h"
#include "py/mphal.h"
#include "i2c.h"
#if MICROPY_HW_ENABLE_HW_I2C
#if defined(STM32F7)
#define I2C_POLL_TIMEOUT_MS (50)
int
i2c_init
(
i2c_t
*
i2c
,
mp_hal_pin_obj_t
scl
,
mp_hal_pin_obj_t
sda
,
uint32_t
freq
)
{
uint32_t
i2c_id
=
((
uint32_t
)
i2c
-
I2C1_BASE
)
/
(
I2C2_BASE
-
I2C1_BASE
);
// Init pins
if
(
!
mp_hal_pin_config_alt
(
scl
,
MP_HAL_PIN_MODE_ALT_OPEN_DRAIN
,
MP_HAL_PIN_PULL_UP
,
AF_FN_I2C
,
i2c_id
+
1
))
{
return
-
MP_EPERM
;
}
if
(
!
mp_hal_pin_config_alt
(
sda
,
MP_HAL_PIN_MODE_ALT_OPEN_DRAIN
,
MP_HAL_PIN_PULL_UP
,
AF_FN_I2C
,
i2c_id
+
1
))
{
return
-
MP_EPERM
;
}
// Enable I2C peripheral clock
RCC
->
APB1ENR
|=
RCC_APB1ENR_I2C1EN
<<
i2c_id
;
volatile
uint32_t
tmp
=
RCC
->
APB1ENR
;
// delay after RCC clock enable
(
void
)
tmp
;
// Initialise I2C peripheral
i2c
->
CR1
=
0
;
i2c
->
CR2
=
0
;
i2c
->
OAR1
=
0
;
i2c
->
OAR2
=
0
;
// These timing values are for f_I2CCLK=54MHz and are only approximate
if
(
freq
>=
1000000
)
{
i2c
->
TIMINGR
=
0x50100103
;
}
else
if
(
freq
>=
400000
)
{
i2c
->
TIMINGR
=
0x70330309
;
}
else
if
(
freq
>=
100000
)
{
i2c
->
TIMINGR
=
0xb0420f13
;
}
else
{
return
-
MP_EINVAL
;
}
i2c
->
TIMEOUTR
=
0
;
return
0
;
}
STATIC
int
i2c_wait_cr2_clear
(
i2c_t
*
i2c
,
uint32_t
mask
)
{
uint32_t
t0
=
HAL_GetTick
();
while
(
i2c
->
CR2
&
mask
)
{
if
(
HAL_GetTick
()
-
t0
>=
I2C_POLL_TIMEOUT_MS
)
{
i2c
->
CR1
&=
~
I2C_CR1_PE
;
return
-
MP_ETIMEDOUT
;
}
}
return
0
;
}
STATIC
int
i2c_wait_isr_set
(
i2c_t
*
i2c
,
uint32_t
mask
)
{
uint32_t
t0
=
HAL_GetTick
();
while
(
!
(
i2c
->
ISR
&
mask
))
{
if
(
HAL_GetTick
()
-
t0
>=
I2C_POLL_TIMEOUT_MS
)
{
i2c
->
CR1
&=
~
I2C_CR1_PE
;
return
-
MP_ETIMEDOUT
;
}
}
return
0
;
}
// len = 0, 1 or N
int
i2c_start_addr
(
i2c_t
*
i2c
,
int
rd_wrn
,
uint16_t
addr
,
size_t
len
,
bool
stop
)
{
// Enable the peripheral and send the START condition with slave address
i2c
->
CR1
|=
I2C_CR1_PE
;
i2c
->
CR2
=
stop
<<
I2C_CR2_AUTOEND_Pos
|
(
len
>
1
)
<<
I2C_CR2_RELOAD_Pos
|
(
len
>
0
)
<<
I2C_CR2_NBYTES_Pos
|
rd_wrn
<<
I2C_CR2_RD_WRN_Pos
|
(
addr
&
0x7f
)
<<
1
;
i2c
->
CR2
|=
I2C_CR2_START
;
// Wait for address to be sent
int
ret
;
if
((
ret
=
i2c_wait_cr2_clear
(
i2c
,
I2C_CR2_START
)))
{
return
ret
;
}
// Check if the slave responded or not
if
(
i2c
->
ISR
&
I2C_ISR_NACKF
)
{
// If we get a NACK then I2C periph releases the bus, so don't send STOP
i2c
->
CR1
&=
~
I2C_CR1_PE
;
return
-
MP_ENODEV
;
}
// Repurpose OAR1 to indicate that we loaded CR2
i2c
->
OAR1
=
1
;
return
0
;
}
STATIC
int
i2c_check_stop
(
i2c_t
*
i2c
)
{
if
(
i2c
->
CR2
&
I2C_CR2_AUTOEND
)
{
// Wait for the STOP condition and then disable the peripheral
int
ret
;
if
((
ret
=
i2c_wait_isr_set
(
i2c
,
I2C_ISR_STOPF
)))
{
return
ret
;
}
i2c
->
CR1
&=
~
I2C_CR1_PE
;
}
return
0
;
}
// next_len = 0 or N
int
i2c_read
(
i2c_t
*
i2c
,
uint8_t
*
dest
,
size_t
len
,
size_t
next_len
)
{
if
(
i2c
->
OAR1
)
{
i2c
->
OAR1
=
0
;
}
else
{
goto
load_cr2
;
}
// Read in the data
while
(
len
--
)
{
int
ret
;
if
((
ret
=
i2c_wait_isr_set
(
i2c
,
I2C_ISR_RXNE
)))
{
return
ret
;
}
*
dest
++
=
i2c
->
RXDR
;
load_cr2:
if
(
len
)
{
i2c
->
CR2
=
(
i2c
->
CR2
&
I2C_CR2_AUTOEND
)
|
(
len
+
next_len
>
1
)
<<
I2C_CR2_RELOAD_Pos
|
1
<<
I2C_CR2_NBYTES_Pos
;
}
}
if
(
!
next_len
)
{
int
ret
;
if
((
ret
=
i2c_check_stop
(
i2c
)))
{
return
ret
;
}
}
return
0
;
}
// next_len = 0 or N
int
i2c_write
(
i2c_t
*
i2c
,
const
uint8_t
*
src
,
size_t
len
,
size_t
next_len
)
{
int
num_acks
=
0
;
if
(
i2c
->
OAR1
)
{
i2c
->
OAR1
=
0
;
}
else
{
goto
load_cr2
;
}
// Write out the data
while
(
len
--
)
{
int
ret
;
if
((
ret
=
i2c_wait_isr_set
(
i2c
,
I2C_ISR_TXE
)))
{
return
ret
;
}
i2c
->
TXDR
=
*
src
++
;
if
((
ret
=
i2c_wait_isr_set
(
i2c
,
I2C_ISR_TCR
|
I2C_ISR_TC
|
I2C_ISR_STOPF
)))
{
return
ret
;
}
if
(
i2c
->
ISR
&
I2C_ISR_NACKF
)
{
// Slave did not respond to byte so stop sending
break
;
}
++
num_acks
;
load_cr2:
if
(
len
)
{
i2c
->
CR2
=
(
i2c
->
CR2
&
I2C_CR2_AUTOEND
)
|
(
len
+
next_len
>
1
)
<<
I2C_CR2_RELOAD_Pos
|
1
<<
I2C_CR2_NBYTES_Pos
;
}
}
if
(
!
next_len
)
{
int
ret
;
if
((
ret
=
i2c_check_stop
(
i2c
)))
{
return
ret
;
}
}
return
num_acks
;
}
int
i2c_readfrom
(
i2c_t
*
i2c
,
uint16_t
addr
,
uint8_t
*
dest
,
size_t
len
,
bool
stop
)
{
int
ret
;
if
((
ret
=
i2c_start_addr
(
i2c
,
1
,
addr
,
len
,
stop
)))
{
return
ret
;
}
return
i2c_read
(
i2c
,
dest
,
len
,
0
);
}
int
i2c_writeto
(
i2c_t
*
i2c
,
uint16_t
addr
,
const
uint8_t
*
src
,
size_t
len
,
bool
stop
)
{
int
ret
;
if
((
ret
=
i2c_start_addr
(
i2c
,
0
,
addr
,
len
,
stop
)))
{
return
ret
;
}
return
i2c_write
(
i2c
,
src
,
len
,
0
);
}
#endif // defined(STM32F7)
#endif // MICROPY_HW_ENABLE_HW_I2C
ports/stm32/i2c.h
浏览文件 @
19778d0a
...
...
@@ -53,4 +53,13 @@ uint32_t pyb_i2c_get_baudrate(I2C_HandleTypeDef *i2c);
void
i2c_ev_irq_handler
(
mp_uint_t
i2c_id
);
void
i2c_er_irq_handler
(
mp_uint_t
i2c_id
);
typedef
I2C_TypeDef
i2c_t
;
int
i2c_init
(
i2c_t
*
i2c
,
mp_hal_pin_obj_t
scl
,
mp_hal_pin_obj_t
sda
,
uint32_t
freq
);
int
i2c_start_addr
(
i2c_t
*
i2c
,
int
rd_wrn
,
uint16_t
addr
,
size_t
len
,
bool
stop
);
int
i2c_read
(
i2c_t
*
i2c
,
uint8_t
*
dest
,
size_t
len
,
size_t
next_len
);
int
i2c_write
(
i2c_t
*
i2c
,
const
uint8_t
*
src
,
size_t
len
,
size_t
next_len
);
int
i2c_readfrom
(
i2c_t
*
i2c
,
uint16_t
addr
,
uint8_t
*
dest
,
size_t
len
,
bool
stop
);
int
i2c_writeto
(
i2c_t
*
i2c
,
uint16_t
addr
,
const
uint8_t
*
src
,
size_t
len
,
bool
stop
);
#endif // MICROPY_INCLUDED_STM32_I2C_H
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录