Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
A
arduino-esp32
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Analytics
Analytics
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
xpstem
arduino-esp32
Commits
ed53b6c8
Unverified
Commit
ed53b6c8
authored
Oct 14, 2021
by
Me No Dev
Committed by
GitHub
Oct 14, 2021
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #5746 from espressif/i2c-slave
I2C Slave Implementation
parents
2e53300d
b145e659
Changes
8
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
1160 additions
and
40 deletions
+1160
-40
CMakeLists.txt
CMakeLists.txt
+1
-0
cores/esp32/esp32-hal-i2c-slave.c
cores/esp32/esp32-hal-i2c-slave.c
+848
-0
cores/esp32/esp32-hal-i2c-slave.h
cores/esp32/esp32-hal-i2c-slave.h
+35
-0
libraries/Wire/examples/WireMaster/WireMaster.ino
libraries/Wire/examples/WireMaster/WireMaster.ino
+30
-0
libraries/Wire/examples/WireScan/WireScan.ino
libraries/Wire/examples/WireScan/WireScan.ino
+28
-0
libraries/Wire/examples/WireSlave/WireSlave.ino
libraries/Wire/examples/WireSlave/WireSlave.ino
+37
-0
libraries/Wire/src/Wire.cpp
libraries/Wire/src/Wire.cpp
+172
-40
libraries/Wire/src/Wire.h
libraries/Wire/src/Wire.h
+9
-0
No files found.
CMakeLists.txt
View file @
ed53b6c8
...
...
@@ -7,6 +7,7 @@ set(CORE_SRCS
cores/esp32/esp32-hal-dac.c
cores/esp32/esp32-hal-gpio.c
cores/esp32/esp32-hal-i2c.c
cores/esp32/esp32-hal-i2c-slave.c
cores/esp32/esp32-hal-ledc.c
cores/esp32/esp32-hal-matrix.c
cores/esp32/esp32-hal-misc.c
...
...
cores/esp32/esp32-hal-i2c-slave.c
0 → 100755
View file @
ed53b6c8
This diff is collapsed.
Click to expand it.
cores/esp32/esp32-hal-i2c-slave.h
0 → 100755
View file @
ed53b6c8
// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#ifdef __cplusplus
extern
"C"
{
#endif
#include "stdint.h"
#include "stddef.h"
#include "esp_err.h"
typedef
void
(
*
i2c_slave_request_cb_t
)
(
uint8_t
num
,
void
*
arg
);
typedef
void
(
*
i2c_slave_receive_cb_t
)
(
uint8_t
num
,
uint8_t
*
data
,
size_t
len
,
bool
stop
,
void
*
arg
);
esp_err_t
i2cSlaveAttachCallbacks
(
uint8_t
num
,
i2c_slave_request_cb_t
request_callback
,
i2c_slave_receive_cb_t
receive_callback
,
void
*
arg
);
esp_err_t
i2cSlaveInit
(
uint8_t
num
,
int
sda
,
int
scl
,
uint16_t
slaveID
,
uint32_t
frequency
,
size_t
rx_len
,
size_t
tx_len
);
esp_err_t
i2cSlaveDeinit
(
uint8_t
num
);
size_t
i2cSlaveWrite
(
uint8_t
num
,
const
uint8_t
*
buf
,
uint32_t
len
,
uint32_t
timeout_ms
);
#ifdef __cplusplus
}
#endif
libraries/Wire/examples/WireMaster/WireMaster.ino
0 → 100644
View file @
ed53b6c8
#include "Wire.h"
#define I2C_DEV_ADDR 0x55
uint32_t
i
=
0
;
void
setup
()
{
Serial
.
begin
(
115200
);
Serial
.
setDebugOutput
(
true
);
Wire
.
begin
();
}
void
loop
()
{
delay
(
5000
);
//Write message to the slave
Wire
.
beginTransmission
(
I2C_DEV_ADDR
);
Wire
.
printf
(
"Hello World! %u"
,
i
++
);
uint8_t
error
=
Wire
.
endTransmission
(
true
);
Serial
.
printf
(
"endTransmission: %u
\n
"
,
error
);
//Read 16 bytes from the slave
error
=
Wire
.
requestFrom
(
I2C_DEV_ADDR
,
16
);
Serial
.
printf
(
"requestFrom: %u
\n
"
,
error
);
if
(
error
){
uint8_t
temp
[
error
];
Wire
.
readBytes
(
temp
,
error
);
log_print_buf
(
temp
,
error
);
}
}
libraries/Wire/examples/WireScan/WireScan.ino
0 → 100644
View file @
ed53b6c8
#include "Wire.h"
void
setup
()
{
Serial
.
begin
(
115200
);
Wire
.
begin
();
}
void
loop
()
{
byte
error
,
address
;
int
nDevices
=
0
;
delay
(
5000
);
Serial
.
println
(
"Scanning for I2C devices ..."
);
for
(
address
=
0x01
;
address
<
0x7f
;
address
++
){
Wire
.
beginTransmission
(
address
);
error
=
Wire
.
endTransmission
();
if
(
error
==
0
){
Serial
.
printf
(
"I2C device found at address 0x%02X
\n
"
,
address
);
nDevices
++
;
}
else
if
(
error
!=
2
){
Serial
.
printf
(
"Error %d at address 0x%02X
\n
"
,
error
,
address
);
}
}
if
(
nDevices
==
0
){
Serial
.
println
(
"No I2C devices found"
);
}
}
libraries/Wire/examples/WireSlave/WireSlave.ino
0 → 100644
View file @
ed53b6c8
#include "Wire.h"
#define I2C_DEV_ADDR 0x55
uint32_t
i
=
0
;
void
onRequest
(){
Wire
.
print
(
i
++
);
Wire
.
print
(
" Packets."
);
Serial
.
println
(
"onRequest"
);
}
void
onReceive
(
int
len
){
Serial
.
printf
(
"onReceive[%d]: "
,
len
);
while
(
Wire
.
available
()){
Serial
.
write
(
Wire
.
read
());
}
Serial
.
println
();
}
void
setup
()
{
Serial
.
begin
(
115200
);
Serial
.
setDebugOutput
(
true
);
Wire
.
onReceive
(
onReceive
);
Wire
.
onRequest
(
onRequest
);
Wire
.
begin
((
uint8_t
)
I2C_DEV_ADDR
);
#if CONFIG_IDF_TARGET_ESP32
char
message
[
64
];
snprintf
(
message
,
64
,
"%u Packets."
,
i
++
);
Wire
.
slaveWrite
((
uint8_t
*
)
message
,
strlen
(
message
));
#endif
}
void
loop
()
{
}
libraries/Wire/src/Wire.cpp
View file @
ed53b6c8
...
...
@@ -30,6 +30,7 @@ extern "C" {
}
#include "esp32-hal-i2c.h"
#include "esp32-hal-i2c-slave.h"
#include "Wire.h"
#include "Arduino.h"
...
...
@@ -47,6 +48,9 @@ TwoWire::TwoWire(uint8_t bus_num)
,
nonStopTask
(
NULL
)
,
lock
(
NULL
)
#endif
,
is_slave
(
false
)
,
user_onRequest
(
NULL
)
,
user_onReceive
(
NULL
)
{}
TwoWire
::~
TwoWire
()
...
...
@@ -59,6 +63,47 @@ TwoWire::~TwoWire()
#endif
}
bool
TwoWire
::
initPins
(
int
sdaPin
,
int
sclPin
)
{
if
(
sdaPin
<
0
)
{
// default param passed
if
(
num
==
0
)
{
if
(
sda
==-
1
)
{
sdaPin
=
SDA
;
//use Default Pin
}
else
{
sdaPin
=
sda
;
// reuse prior pin
}
}
else
{
if
(
sda
==-
1
)
{
log_e
(
"no Default SDA Pin for Second Peripheral"
);
return
false
;
//no Default pin for Second Peripheral
}
else
{
sdaPin
=
sda
;
// reuse prior pin
}
}
}
if
(
sclPin
<
0
)
{
// default param passed
if
(
num
==
0
)
{
if
(
scl
==
-
1
)
{
sclPin
=
SCL
;
// use Default pin
}
else
{
sclPin
=
scl
;
// reuse prior pin
}
}
else
{
if
(
scl
==
-
1
)
{
log_e
(
"no Default SCL Pin for Second Peripheral"
);
return
false
;
//no Default pin for Second Peripheral
}
else
{
sclPin
=
scl
;
// reuse prior pin
}
}
}
sda
=
sdaPin
;
scl
=
sclPin
;
return
true
;
}
bool
TwoWire
::
setPins
(
int
sdaPin
,
int
sclPin
)
{
#if !CONFIG_DISABLE_HAL_LOCKS
...
...
@@ -76,8 +121,7 @@ bool TwoWire::setPins(int sdaPin, int sclPin)
}
#endif
if
(
!
i2cIsInit
(
num
)){
sda
=
sdaPin
;
scl
=
sclPin
;
initPins
(
sdaPin
,
sclPin
);
}
else
{
log_e
(
"bus already initialized. change pins only when not."
);
}
...
...
@@ -88,10 +132,10 @@ bool TwoWire::setPins(int sdaPin, int sclPin)
return
!
i2cIsInit
(
num
);
}
bool
TwoWire
::
begin
(
int
sdaPin
,
int
sclPin
,
uint32_t
frequency
)
// Slave Begin
bool
TwoWire
::
begin
(
uint8_t
addr
,
int
sdaPin
,
int
sclPin
,
uint32_t
frequency
)
{
bool
started
=
false
;
esp_err_t
err
=
ESP_OK
;
#if !CONFIG_DISABLE_HAL_LOCKS
if
(
lock
==
NULL
){
lock
=
xSemaphoreCreateMutex
();
...
...
@@ -106,46 +150,64 @@ bool TwoWire::begin(int sdaPin, int sclPin, uint32_t frequency)
return
false
;
}
#endif
if
(
i2cIsInit
(
num
)){
if
(
is_slave
){
log_w
(
"Bus already started in Slave Mode."
);
started
=
true
;
goto
end
;
}
if
(
sdaPin
<
0
)
{
// default param passed
if
(
num
==
0
)
{
if
(
sda
==-
1
)
{
sdaPin
=
SDA
;
//use Default Pin
}
else
{
sdaPin
=
sda
;
// reuse prior pin
}
}
else
{
if
(
sda
==-
1
)
{
log_e
(
"no Default SDA Pin for Second Peripheral"
);
goto
end
;
//no Default pin for Second Peripheral
}
else
{
sdaPin
=
sda
;
// reuse prior pin
}
}
if
(
i2cIsInit
(
num
)){
log_e
(
"Bus already started in Master Mode."
);
goto
end
;
}
if
(
!
initPins
(
sdaPin
,
sclPin
)){
goto
end
;
}
i2cSlaveAttachCallbacks
(
num
,
onRequestService
,
onReceiveService
,
this
);
if
(
i2cSlaveInit
(
num
,
sda
,
scl
,
addr
,
frequency
,
I2C_BUFFER_LENGTH
,
I2C_BUFFER_LENGTH
)
!=
ESP_OK
){
log_e
(
"Slave Init ERROR"
);
goto
end
;
}
is_slave
=
true
;
started
=
true
;
end:
#if !CONFIG_DISABLE_HAL_LOCKS
//release lock
xSemaphoreGive
(
lock
);
#endif
return
started
;
}
if
(
sclPin
<
0
)
{
// default param passed
if
(
num
==
0
)
{
if
(
scl
==
-
1
)
{
sclPin
=
SCL
;
// use Default pin
}
else
{
sclPin
=
scl
;
// reuse prior pin
}
}
else
{
if
(
scl
==
-
1
)
{
log_e
(
"no Default SCL Pin for Second Peripheral"
);
goto
end
;
//no Default pin for Second Peripheral
}
else
{
sclPin
=
scl
;
// reuse prior pin
}
// Master Begin
bool
TwoWire
::
begin
(
int
sdaPin
,
int
sclPin
,
uint32_t
frequency
)
{
bool
started
=
false
;
esp_err_t
err
=
ESP_OK
;
#if !CONFIG_DISABLE_HAL_LOCKS
if
(
lock
==
NULL
){
lock
=
xSemaphoreCreateMutex
();
if
(
lock
==
NULL
){
log_e
(
"xSemaphoreCreateMutex failed"
);
return
false
;
}
}
sda
=
sdaPin
;
scl
=
sclPin
;
//acquire lock
if
(
xSemaphoreTake
(
lock
,
portMAX_DELAY
)
!=
pdTRUE
){
log_e
(
"could not acquire lock"
);
return
false
;
}
#endif
if
(
is_slave
){
log_e
(
"Bus already started in Slave Mode."
);
goto
end
;
}
if
(
i2cIsInit
(
num
)){
log_w
(
"Bus already started in Master Mode."
);
started
=
true
;
goto
end
;
}
if
(
!
initPins
(
sdaPin
,
sclPin
)){
goto
end
;
}
err
=
i2cInit
(
num
,
sda
,
scl
,
frequency
);
started
=
(
err
==
ESP_OK
);
...
...
@@ -169,7 +231,12 @@ bool TwoWire::end()
return
false
;
}
#endif
if
(
i2cIsInit
(
num
)){
if
(
is_slave
){
err
=
i2cSlaveDeinit
(
num
);
if
(
err
==
ESP_OK
){
is_slave
=
false
;
}
}
else
if
(
i2cIsInit
(
num
)){
err
=
i2cDeinit
(
num
);
}
#if !CONFIG_DISABLE_HAL_LOCKS
...
...
@@ -189,7 +256,11 @@ uint32_t TwoWire::getClock()
log_e
(
"could not acquire lock"
);
}
else
{
#endif
i2cGetClock
(
num
,
&
frequency
);
if
(
is_slave
){
log_e
(
"Bus is in Slave Mode"
);
}
else
{
i2cGetClock
(
num
,
&
frequency
);
}
#if !CONFIG_DISABLE_HAL_LOCKS
//release lock
xSemaphoreGive
(
lock
);
...
...
@@ -208,7 +279,12 @@ bool TwoWire::setClock(uint32_t frequency)
return
false
;
}
#endif
err
=
i2cSetClock
(
num
,
frequency
);
if
(
is_slave
){
log_e
(
"Bus is in Slave Mode"
);
err
=
ESP_FAIL
;
}
else
{
err
=
i2cSetClock
(
num
,
frequency
);
}
#if !CONFIG_DISABLE_HAL_LOCKS
//release lock
xSemaphoreGive
(
lock
);
...
...
@@ -228,6 +304,10 @@ uint16_t TwoWire::getTimeOut()
void
TwoWire
::
beginTransmission
(
uint16_t
address
)
{
if
(
is_slave
){
log_e
(
"Bus is in Slave Mode"
);
return
;
}
#if !CONFIG_DISABLE_HAL_LOCKS
if
(
nonStop
&&
nonStopTask
==
xTaskGetCurrentTaskHandle
()){
log_e
(
"Unfinished Repeated Start transaction! Expected requestFrom, not beginTransmission! Clearing..."
);
...
...
@@ -247,6 +327,10 @@ void TwoWire::beginTransmission(uint16_t address)
uint8_t
TwoWire
::
endTransmission
(
bool
sendStop
)
{
if
(
is_slave
){
log_e
(
"Bus is in Slave Mode"
);
return
4
;
}
esp_err_t
err
=
ESP_OK
;
if
(
sendStop
){
err
=
i2cWrite
(
num
,
txAddress
,
txBuffer
,
txLength
,
_timeOutMillis
);
...
...
@@ -272,6 +356,10 @@ uint8_t TwoWire::endTransmission(bool sendStop)
uint8_t
TwoWire
::
requestFrom
(
uint16_t
address
,
uint8_t
size
,
bool
sendStop
)
{
if
(
is_slave
){
log_e
(
"Bus is in Slave Mode"
);
return
0
;
}
esp_err_t
err
=
ESP_OK
;
if
(
nonStop
#if !CONFIG_DISABLE_HAL_LOCKS
...
...
@@ -402,5 +490,49 @@ uint8_t TwoWire::endTransmission(void)
return
endTransmission
(
true
);
}
size_t
TwoWire
::
slaveWrite
(
const
uint8_t
*
buffer
,
size_t
len
)
{
return
i2cSlaveWrite
(
num
,
buffer
,
len
,
_timeOutMillis
);
}
void
TwoWire
::
onReceiveService
(
uint8_t
num
,
uint8_t
*
inBytes
,
size_t
numBytes
,
bool
stop
,
void
*
arg
)
{
TwoWire
*
wire
=
(
TwoWire
*
)
arg
;
if
(
!
wire
->
user_onReceive
){
return
;
}
for
(
uint8_t
i
=
0
;
i
<
numBytes
;
++
i
){
wire
->
rxBuffer
[
i
]
=
inBytes
[
i
];
}
wire
->
rxIndex
=
0
;
wire
->
rxLength
=
numBytes
;
wire
->
user_onReceive
(
numBytes
);
}
void
TwoWire
::
onRequestService
(
uint8_t
num
,
void
*
arg
)
{
TwoWire
*
wire
=
(
TwoWire
*
)
arg
;
if
(
!
wire
->
user_onRequest
){
return
;
}
wire
->
txLength
=
0
;
wire
->
user_onRequest
();
if
(
wire
->
txLength
){
wire
->
slaveWrite
((
uint8_t
*
)
wire
->
txBuffer
,
wire
->
txLength
);
}
}
void
TwoWire
::
onReceive
(
void
(
*
function
)(
int
)
)
{
user_onReceive
=
function
;
}
// sets function called on slave read
void
TwoWire
::
onRequest
(
void
(
*
function
)(
void
)
)
{
user_onRequest
=
function
;
}
TwoWire
Wire
=
TwoWire
(
0
);
TwoWire
Wire1
=
TwoWire
(
1
);
libraries/Wire/src/Wire.h
View file @
ed53b6c8
...
...
@@ -61,6 +61,13 @@ protected:
TaskHandle_t
nonStopTask
;
SemaphoreHandle_t
lock
;
#endif
private:
bool
is_slave
;
void
(
*
user_onRequest
)(
void
);
void
(
*
user_onReceive
)(
int
);
static
void
onRequestService
(
uint8_t
,
void
*
);
static
void
onReceiveService
(
uint8_t
,
uint8_t
*
,
size_t
,
bool
,
void
*
);
bool
initPins
(
int
sdaPin
,
int
sclPin
);
public:
TwoWire
(
uint8_t
bus_num
);
...
...
@@ -70,6 +77,7 @@ public:
bool
setPins
(
int
sda
,
int
scl
);
bool
begin
(
int
sda
=-
1
,
int
scl
=-
1
,
uint32_t
frequency
=
0
);
// returns true, if successful init of i2c bus
bool
begin
(
uint8_t
slaveAddr
,
int
sda
=-
1
,
int
scl
=-
1
,
uint32_t
frequency
=
0
);
bool
end
();
void
setTimeOut
(
uint16_t
timeOutMillis
);
// default timeout of i2c transactions is 50ms
...
...
@@ -123,6 +131,7 @@ public:
void
onReceive
(
void
(
*
)(
int
)
);
void
onRequest
(
void
(
*
)(
void
)
);
size_t
slaveWrite
(
const
uint8_t
*
,
size_t
);
};
extern
TwoWire
Wire
;
...
...
Write
Preview
Markdown
is supported
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