Skip to content

Commit 669d668

Browse files
fprfpistm
fpr
authored andcommitted
I2C functions validated
Specific Wire examples for STM32F1xx added. Signed-off-by: fpr <fabien.perroquin@wi6labs.com>
1 parent a47ca8e commit 669d668

File tree

5 files changed

+222
-1
lines changed

5 files changed

+222
-1
lines changed

cores/arduino/stm32/twi.c

+90-1
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,10 @@
4747
/** @addtogroup STM32F4xx_System_Private_Includes
4848
* @{
4949
*/
50-
5150
#include "stm32_def.h"
5251
#include "hw_config.h"
5352
#include "twi.h"
53+
#include "PinAF_STM32F1.h"
5454

5555
/**
5656
* @}
@@ -168,6 +168,9 @@ void i2c_custom_init(i2c_t *obj, i2c_timing_e timing, uint32_t addressingMode, u
168168
__HAL_RCC_I2C1_FORCE_RESET();
169169
__HAL_RCC_I2C1_RELEASE_RESET();
170170
obj->irq = I2C1_EV_IRQn;
171+
#ifdef STM32F1xx
172+
obj->irqER = I2C1_ER_IRQn;
173+
#endif
171174
i2c_handles[0] = handle;
172175
}
173176
#endif
@@ -181,6 +184,9 @@ void i2c_custom_init(i2c_t *obj, i2c_timing_e timing, uint32_t addressingMode, u
181184
obj->irq = I2C2_IRQn;
182185
#else
183186
obj->irq = I2C2_EV_IRQn;
187+
#ifdef STM32F1xx
188+
obj->irqER = I2C2_ER_IRQn;
189+
#endif
184190
#endif
185191
i2c_handles[1] = handle;
186192
}
@@ -212,7 +218,11 @@ void i2c_custom_init(i2c_t *obj, i2c_timing_e timing, uint32_t addressingMode, u
212218
GPIO_InitStruct.Mode = STM_PIN_MODE(pinmap_function(obj->scl,PinMap_I2C_SCL));
213219
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
214220
GPIO_InitStruct.Pull = STM_PIN_PUPD(pinmap_function(obj->scl,PinMap_I2C_SCL));
221+
#ifdef STM32F1xx
222+
pin_SetF1AFPin(STM_PIN_AFNUM(pinmap_function(obj->scl,PinMap_I2C_SCL)));
223+
#else
215224
GPIO_InitStruct.Alternate = STM_PIN_AFNUM(pinmap_function(obj->scl,PinMap_I2C_SCL));
225+
#endif /* STM32F1xx */
216226
HAL_GPIO_Init(port, &GPIO_InitStruct);
217227

218228
//SDA
@@ -221,7 +231,11 @@ void i2c_custom_init(i2c_t *obj, i2c_timing_e timing, uint32_t addressingMode, u
221231
GPIO_InitStruct.Mode = STM_PIN_MODE(pinmap_function(obj->sda,PinMap_I2C_SDA));
222232
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
223233
GPIO_InitStruct.Pull = STM_PIN_PUPD(pinmap_function(obj->sda,PinMap_I2C_SDA));
234+
#ifdef STM32F1xx
235+
pin_SetF1AFPin(STM_PIN_AFNUM(pinmap_function(obj->sda,PinMap_I2C_SDA)));
236+
#else
224237
GPIO_InitStruct.Alternate = STM_PIN_AFNUM(pinmap_function(obj->sda,PinMap_I2C_SDA));
238+
#endif /* STM32F1xx */
225239
HAL_GPIO_Init(port, &GPIO_InitStruct);
226240

227241
handle->Instance = obj->i2c;
@@ -242,6 +256,10 @@ void i2c_custom_init(i2c_t *obj, i2c_timing_e timing, uint32_t addressingMode, u
242256
if(master == 0) {
243257
HAL_NVIC_SetPriority(obj->irq, 0, 1);
244258
HAL_NVIC_EnableIRQ(obj->irq);
259+
#ifdef STM32F1xx
260+
HAL_NVIC_SetPriority(obj->irqER, 0, 1);
261+
HAL_NVIC_EnableIRQ(obj->irqER);
262+
#endif
245263
}
246264

247265
// Init the I2C
@@ -256,6 +274,9 @@ void i2c_custom_init(i2c_t *obj, i2c_timing_e timing, uint32_t addressingMode, u
256274
void i2c_deinit(i2c_t *obj)
257275
{
258276
HAL_NVIC_DisableIRQ(obj->irq);
277+
#ifdef STM32F1xx
278+
HAL_NVIC_DisableIRQ(obj->irqER);
279+
#endif
259280
HAL_I2C_DeInit(&(obj->handle));
260281
}
261282

@@ -402,8 +423,16 @@ i2c_t *get_i2c_obj(I2C_HandleTypeDef *hi2c){
402423
*/
403424
void i2c_attachSlaveRxEvent(i2c_t *obj, void (*function)(uint8_t*, int) )
404425
{
426+
if((obj == NULL) || (function == NULL))
427+
return;
428+
405429
obj->i2c_onSlaveReceive = function;
430+
#ifdef STM32F1xx
431+
obj->i2cTxRxBufferSize = 0;
432+
HAL_I2C_Slave_Receive_IT(&(obj->handle), obj->i2cTxRxBuffer, I2C_TXRX_BUFFER_SIZE);
433+
#else
406434
HAL_I2C_EnableListen_IT(&(obj->handle));
435+
#endif
407436
}
408437

409438
/** @brief sets function called before a slave write operation
@@ -413,10 +442,64 @@ void i2c_attachSlaveRxEvent(i2c_t *obj, void (*function)(uint8_t*, int) )
413442
*/
414443
void i2c_attachSlaveTxEvent(i2c_t *obj, void (*function)(void) )
415444
{
445+
if((obj == NULL) || (function == NULL))
446+
return;
447+
416448
obj->i2c_onSlaveTransmit = function;
449+
#ifdef STM32F1xx
450+
/* Fill i2c buffer with data to transmit otherwize the buffer will be empty
451+
when master will read the data for the first time */
452+
obj->i2cTxRxBufferSize = 0;
453+
obj->i2c_onSlaveTransmit();
454+
HAL_I2C_Slave_Transmit_IT(&(obj->handle), obj->i2cTxRxBuffer, obj->i2cTxRxBufferSize);
455+
#else
417456
HAL_I2C_EnableListen_IT(&(obj->handle));
457+
#endif
458+
}
459+
460+
#ifdef STM32F1xx
461+
462+
/** @brief Slave Tx Transfer completed callback.
463+
* @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
464+
* the configuration information for the specified I2C.
465+
* @retval None
466+
*/
467+
void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *hi2c)
468+
{
469+
i2c_t *obj = get_i2c_obj(hi2c);
470+
471+
if(NULL != obj->i2c_onSlaveTransmit) {
472+
// reset buffer size and fill buffer with new data before the next Tx
473+
obj->i2cTxRxBufferSize = 0;
474+
obj->i2c_onSlaveTransmit();
475+
HAL_I2C_Slave_Transmit_IT(hi2c, obj->i2cTxRxBuffer, obj->i2cTxRxBufferSize);
476+
}
477+
}
478+
479+
/**
480+
* @brief Slave Rx Transfer completed callback.
481+
* @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
482+
* the configuration information for the specified I2C.
483+
* @retval None
484+
*/
485+
void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c)
486+
{
487+
uint8_t nbData = 0;
488+
i2c_t *obj = get_i2c_obj(hi2c);
489+
490+
if(NULL != obj->i2c_onSlaveReceive) {
491+
nbData = I2C_TXRX_BUFFER_SIZE - obj->handle.XferCount;
492+
493+
if(nbData != 0) {
494+
obj->i2c_onSlaveReceive(obj->i2cTxRxBuffer, nbData);
495+
}
496+
497+
HAL_I2C_Slave_Receive_IT(hi2c, obj->i2cTxRxBuffer, I2C_TXRX_BUFFER_SIZE);
498+
}
418499
}
419500

501+
#else /* Others */
502+
420503
/**
421504
* @brief Slave Address Match callback.
422505
* @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
@@ -469,6 +552,8 @@ void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c)
469552
HAL_I2C_EnableListen_IT(hi2c);
470553
}
471554

555+
#endif /* STM32F1xx */
556+
472557
/**
473558
* @brief I2C error callback.
474559
* @param hi2c Pointer to a I2C_HandleTypeDef structure that contains
@@ -477,7 +562,11 @@ void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c)
477562
*/
478563
void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c)
479564
{
565+
#ifdef STM32F1xx
566+
UNUSED(hi2c);
567+
#else
480568
HAL_I2C_EnableListen_IT(hi2c);
569+
#endif
481570
}
482571

483572
/**

cores/arduino/stm32/twi.h

+3
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ struct i2c_s {
6767
PinName sda;
6868
PinName scl;
6969
IRQn_Type irq;
70+
#ifdef STM32F1xx
71+
IRQn_Type irqER;
72+
#endif
7073
uint8_t slaveMode;
7174
void (*i2c_onSlaveReceive)(uint8_t *, int);
7275
void (*i2c_onSlaveTransmit)(void);

libraries/Wire/Wire.cpp

+15
Original file line numberDiff line numberDiff line change
@@ -81,13 +81,15 @@ void TwoWire::begin(uint8_t address)
8181

8282
i2c_custom_init(&_i2c,I2C_100KHz,I2C_ADDRESSINGMODE_7BIT,ownAddress,master);
8383

84+
#ifndef STM32F1xx
8485
if(master == false){
8586
// i2c_attachSlaveTxEvent(&_i2c, reinterpret_cast<void(*)(i2c_t*)>(&TwoWire::onRequestService));
8687
// i2c_attachSlaveRxEvent(&_i2c, reinterpret_cast<void(*)(i2c_t*, uint8_t*, int)>(&TwoWire::onReceiveService));
8788

8889
i2c_attachSlaveTxEvent(&_i2c, onRequestService);
8990
i2c_attachSlaveRxEvent(&_i2c, onReceiveService);
9091
}
92+
#endif
9193
}
9294

9395
void TwoWire::begin(int address)
@@ -109,6 +111,8 @@ uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint32_t iaddres
109111
{
110112
UNUSED(sendStop);
111113
if (master == true) {
114+
//NOTE: do not work with STM32F1xx boards (latest HAL version: 1.0.4)
115+
#ifndef STM32F1xx
112116
if (isize > 0) {
113117
// send internal address; this mode allows sending a repeated start to access
114118
// some devices' internal registers. This function is executed by the hardware
@@ -127,6 +131,7 @@ uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint32_t iaddres
127131
}
128132
endTransmission(false);
129133
}
134+
#endif /* !STM32F1xx */
130135

131136
// clamp to buffer length
132137
if(quantity > BUFFER_LENGTH){
@@ -369,12 +374,22 @@ void TwoWire::onRequestService(void)
369374
void TwoWire::onReceive( void (*function)(int) )
370375
{
371376
user_onReceive = function;
377+
378+
#ifdef STM32F1xx
379+
//Enable slave receive IT
380+
i2c_attachSlaveRxEvent(&_i2c, onReceiveService);
381+
#endif
372382
}
373383

374384
// sets function called on slave read
375385
void TwoWire::onRequest( void (*function)(void) )
376386
{
377387
user_onRequest = function;
388+
389+
#ifdef STM32F1xx
390+
//Enable slave transmit IT
391+
i2c_attachSlaveTxEvent(&_i2c, onRequestService);
392+
#endif
378393
}
379394

380395
// Preinstantiate Objects //////////////////////////////////////////////////////
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/* Wire Master Reader Writer
2+
by Wi6Labs
3+
4+
Demonstrates use of the Wire library, particullary with STM32F1xx boards.
5+
Reads/writes data from/to an I2C/TWI slave device.
6+
Refer to the "Wire Slave Sender Receiver" example for use with this.
7+
8+
Created 27 June 2017
9+
10+
This example code is in the public domain.
11+
*/
12+
13+
#include <Wire.h>
14+
15+
#define I2C_ADDR 2
16+
17+
byte x = 0;
18+
19+
void setup()
20+
{
21+
Wire.begin(); // join i2c bus (address optional for master)
22+
Serial.begin(9600); // start serial for output
23+
}
24+
25+
void loop()
26+
{
27+
Wire.requestFrom(I2C_ADDR, 6); // request 6 bytes from slave device
28+
29+
while(Wire.available()) // slave may send less than requested
30+
{
31+
char c = Wire.read(); // receive a byte as character
32+
Serial.print(c); // print the character
33+
}
34+
35+
delay(10);
36+
37+
Wire.beginTransmission(I2C_ADDR); // transmit to device
38+
Wire.write("x is "); // sends five bytes
39+
Wire.write(x); // sends one byte
40+
Wire.endTransmission(); // stop transmitting
41+
x++;
42+
43+
delay(1000);
44+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/* Wire Slave Receiver
2+
by Wi6Labs
3+
4+
Demonstrates use of the Wire library, particullary with STM32F1xx boards where
5+
we can't use slave Tx & Rx mode in same time.
6+
Receives/sends data as an I2C/TWI slave device.
7+
Refer to the "Wire Master Reader Writer" example for use with this.
8+
9+
Created 27 June 2017
10+
11+
This example code is in the public domain.
12+
*/
13+
14+
#include <Wire.h>
15+
16+
#define SLAVE_MODE_RX 0
17+
#define SLAVE_MODE_TX 1
18+
19+
#define I2C_ADDR 2
20+
21+
int w_r_mode = SLAVE_MODE_TX;
22+
bool switch_mode = false;
23+
24+
void setup()
25+
{
26+
Wire.begin(I2C_ADDR); // join i2c bus with address #4
27+
Wire.onRequest(requestEvent); // register event
28+
Serial.begin(9600); // start serial for output
29+
}
30+
31+
void loop()
32+
{
33+
if(switch_mode == true) {
34+
switch_mode = false;
35+
Wire.end();
36+
Wire.begin(I2C_ADDR);
37+
if(w_r_mode == SLAVE_MODE_TX) {
38+
Wire.onRequest(requestEvent); // register event
39+
} else {
40+
Wire.onReceive(receiveEvent); // register event
41+
}
42+
}
43+
}
44+
45+
// function that executes whenever data is received from master
46+
// this function is registered as an event, see setup()
47+
void receiveEvent(int howMany)
48+
{
49+
while(1 < Wire.available()) // loop through all but the last
50+
{
51+
char c = Wire.read(); // receive byte as a character
52+
Serial.print(c); // print the character
53+
}
54+
int x = Wire.read(); // receive byte as an integer
55+
Serial.println(x); // print the integer
56+
57+
switch_mode = true;
58+
w_r_mode = SLAVE_MODE_TX;
59+
}
60+
61+
// function that executes whenever data is requested by master
62+
// this function is registered as an event, see setup()
63+
void requestEvent()
64+
{
65+
Wire.write("hello "); // respond with message of 6 bytes
66+
// as expected by master
67+
68+
switch_mode = true;
69+
w_r_mode = SLAVE_MODE_RX;
70+
}

0 commit comments

Comments
 (0)