Skip to content

Commit ddcd3ad

Browse files
authored
Merge pull request #3488 from LMESTM/dev_stm_i2c_v2_unitary_functions
Dev stm i2c v2 unitary functions
2 parents 9af3173 + 4297e3f commit ddcd3ad

File tree

8 files changed

+141
-61
lines changed

8 files changed

+141
-61
lines changed

features/unsupported/tests/mbed/i2c_master_slave/main.cpp

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
#error [NOT_SUPPORTED] Target has only one I2C instance
2323
#endif
2424

25-
#define ADDR (0xA0)
25+
#define ADDR (0x80)
2626
#define FREQ 100000
2727

2828
// ********************************************************
@@ -89,11 +89,8 @@ int main()
8989
master.start();
9090
master.write(ADDR);
9191
master.write(sent);
92-
if(slave.receive() != I2CSlave::WriteAddressed)
93-
{
94-
notify_completion(false);
95-
return 1;
96-
}
92+
while(slave.receive() != I2CSlave::WriteAddressed);
93+
9794
slave.read(&received, 1);
9895
if(sent != received)
9996
{
@@ -105,14 +102,11 @@ int main()
105102
// Second transfer: slave to master
106103
master.start();
107104
master.write(ADDR | 1);
108-
if(slave.receive() != I2CSlave::ReadAddressed)
109-
{
110-
notify_completion(false);
111-
return 1;
112-
}
105+
while(slave.receive() != I2CSlave::ReadAddressed);
106+
113107
slave.write(received);
114108
received = master.read(0);
115-
slave.stop();
109+
master.stop();
116110
notify_completion(received == sent);
117111
}
118112

features/unsupported/tests/mbed/i2c_master_slave_asynch/main.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ I2C master(D14, D15); // I2C_SDA, I2C_SCL
4141
defined (TARGET_DISCO_F429ZI) || \
4242
defined (TARGET_NUCLEO_F767ZI) || \
4343
defined (TARGET_NUCLEO_L053R8) || \
44+
defined (TARGET_NUCLEO_L073RZ) || \
4445
defined (TARGET_NUCLEO_L152RE) || \
4546
defined (TARGET_NUCLEO_L476RG)
4647
I2CSlave slave(PB_11, PB_10);

targets/TARGET_STM/TARGET_STM32F0/common_objects.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ struct i2c_s {
9898
IRQn_Type error_i2cIRQ;
9999
uint32_t XferOperation;
100100
volatile uint8_t event;
101+
volatile int pending_start;
101102
#if DEVICE_I2CSLAVE
102103
uint8_t slave;
103104
volatile uint8_t pending_slave_tx_master_rx;

targets/TARGET_STM/TARGET_STM32F3/common_objects.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ struct i2c_s {
9898
IRQn_Type error_i2cIRQ;
9999
uint32_t XferOperation;
100100
volatile uint8_t event;
101+
volatile int pending_start;
101102
#if DEVICE_I2CSLAVE
102103
uint8_t slave;
103104
volatile uint8_t pending_slave_tx_master_rx;

targets/TARGET_STM/TARGET_STM32F7/common_objects.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ struct i2c_s {
9898
IRQn_Type error_i2cIRQ;
9999
uint32_t XferOperation;
100100
volatile uint8_t event;
101+
volatile int pending_start;
101102
#if DEVICE_I2CSLAVE
102103
uint8_t slave;
103104
volatile uint8_t pending_slave_tx_master_rx;

targets/TARGET_STM/TARGET_STM32L0/common_objects.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ struct i2c_s {
9898
IRQn_Type error_i2cIRQ;
9999
uint32_t XferOperation;
100100
volatile uint8_t event;
101+
volatile int pending_start;
101102
#if DEVICE_I2CSLAVE
102103
uint8_t slave;
103104
volatile uint8_t pending_slave_tx_master_rx;

targets/TARGET_STM/TARGET_STM32L4/common_objects.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ struct i2c_s {
9898
IRQn_Type error_i2cIRQ;
9999
uint32_t XferOperation;
100100
volatile uint8_t event;
101+
volatile int pending_start;
101102
#if DEVICE_I2CSLAVE
102103
uint8_t slave;
103104
volatile uint8_t pending_slave_tx_master_rx;

targets/TARGET_STM/i2c_api.c

Lines changed: 129 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,9 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
341341
// I2C Xfer operation init
342342
obj_s->event = 0;
343343
obj_s->XferOperation = I2C_FIRST_AND_LAST_FRAME;
344+
#ifdef I2C_IP_VERSION_V2
345+
obj_s->pending_start = 0;
346+
#endif
344347
}
345348

346349
void i2c_frequency(i2c_t *obj, int hz)
@@ -440,6 +443,14 @@ i2c_t *get_i2c_obj(I2C_HandleTypeDef *hi2c){
440443
return (obj);
441444
}
442445

446+
void i2c_reset(i2c_t *obj) {
447+
struct i2c_s *obj_s = I2C_S(obj);
448+
/* As recommended in i2c_api.h, mainly send stop */
449+
i2c_stop(obj);
450+
/* then re-init */
451+
i2c_init(obj, obj_s->sda, obj_s->scl);
452+
}
453+
443454
/*
444455
* UNITARY APIS.
445456
* For very basic operations, direct registers access is needed
@@ -535,7 +546,7 @@ int i2c_byte_write(i2c_t *obj, int data) {
535546
(__HAL_I2C_GET_FLAG(handle, I2C_FLAG_BTF) == RESET) &&
536547
(__HAL_I2C_GET_FLAG(handle, I2C_FLAG_ADDR) == RESET)) {
537548
if ((timeout--) == 0) {
538-
return 0;
549+
return 2;
539550
}
540551
}
541552

@@ -548,92 +559,161 @@ int i2c_byte_write(i2c_t *obj, int data) {
548559
}
549560
#endif //I2C_IP_VERSION_V1
550561
#ifdef I2C_IP_VERSION_V2
562+
551563
int i2c_start(i2c_t *obj) {
552564
struct i2c_s *obj_s = I2C_S(obj);
553-
I2C_HandleTypeDef *handle = &(obj_s->handle);
554-
I2C_TypeDef *i2c = (I2C_TypeDef *)obj_s->i2c;
555-
int timeout;
556-
557-
// Clear Acknowledge failure flag
558-
__HAL_I2C_CLEAR_FLAG(handle, I2C_FLAG_AF);
565+
/* This I2C IP doesn't */
566+
obj_s->pending_start = 1;
567+
return 0;
568+
}
559569

560-
// Wait the STOP condition has been previously correctly sent
561-
timeout = FLAG_TIMEOUT;
562-
while ((i2c->CR2 & I2C_CR2_STOP) == I2C_CR2_STOP){
563-
if ((timeout--) == 0) {
564-
return 1;
565-
}
570+
int i2c_stop(i2c_t *obj) {
571+
struct i2c_s *obj_s = I2C_S(obj);
572+
I2C_HandleTypeDef *handle = &(obj_s->handle);
573+
int timeout = FLAG_TIMEOUT;
574+
#if DEVICE_I2CSLAVE
575+
if (obj_s->slave) {
576+
/* re-init slave when stop is requested */
577+
i2c_init(obj, obj_s->sda, obj_s->scl);
578+
return 0;
566579
}
580+
#endif
581+
// Disable reload mode
582+
handle->Instance->CR2 &= (uint32_t)~I2C_CR2_RELOAD;
583+
// Generate the STOP condition
584+
handle->Instance->CR2 |= I2C_CR2_STOP;
567585

568-
// Generate the START condition
569-
i2c->CR2 |= I2C_CR2_START;
570-
571-
// Wait the START condition has been correctly sent
572586
timeout = FLAG_TIMEOUT;
573-
while (__HAL_I2C_GET_FLAG(handle, I2C_FLAG_BUSY) == RESET) {
587+
while (!__HAL_I2C_GET_FLAG(handle, I2C_FLAG_STOPF)) {
574588
if ((timeout--) == 0) {
575-
return 1;
589+
return I2C_ERROR_BUS_BUSY;
576590
}
577591
}
578592

579-
return 0;
580-
}
593+
/* Clear STOP Flag */
594+
__HAL_I2C_CLEAR_FLAG(handle, I2C_FLAG_STOPF);
581595

582-
int i2c_stop(i2c_t *obj) {
583-
struct i2c_s *obj_s = I2C_S(obj);
584-
I2C_TypeDef *i2c = (I2C_TypeDef *)obj_s->i2c;
596+
/* Erase slave address, this wiil be used as a marker
597+
* to know when we need to prepare next start */
598+
handle->Instance->CR2 &= ~I2C_CR2_SADD;
585599

586-
// Generate the STOP condition
587-
i2c->CR2 |= I2C_CR2_STOP;
600+
/* In case of mixed usage of the APIs (unitary + SYNC)
601+
* re-inti HAL state */
602+
if (obj_s->XferOperation != I2C_FIRST_AND_LAST_FRAME) {
603+
i2c_init(obj, obj_s->sda, obj_s->scl);
604+
}
588605

589606
return 0;
590607
}
591608

592609
int i2c_byte_read(i2c_t *obj, int last) {
593610
struct i2c_s *obj_s = I2C_S(obj);
594-
I2C_TypeDef *i2c = (I2C_TypeDef *)obj_s->i2c;
595611
I2C_HandleTypeDef *handle = &(obj_s->handle);
596-
int timeout;
612+
int timeout = FLAG_TIMEOUT;
613+
uint32_t tmpreg = handle->Instance->CR2;
614+
char data;
615+
#if DEVICE_I2CSLAVE
616+
if (obj_s->slave) {
617+
return i2c_slave_read(obj, &data, 1);
618+
}
619+
#endif
620+
/* Then send data when there's room in the TX fifo */
621+
if ((tmpreg & I2C_CR2_RELOAD) != 0) {
622+
while (!__HAL_I2C_GET_FLAG(handle, I2C_FLAG_TCR)) {
623+
if ((timeout--) == 0) {
624+
DEBUG_PRINTF("timeout in byte_read\r\n");
625+
return -1;
626+
}
627+
}
628+
}
629+
630+
/* Enable reload mode as we don't know how many bytes will eb sent */
631+
handle->Instance->CR2 |= I2C_CR2_RELOAD;
632+
/* Set transfer size to 1 */
633+
handle->Instance->CR2 |= (I2C_CR2_NBYTES & (1 << 16));
634+
/* Set the prepared configuration */
635+
handle->Instance->CR2 = tmpreg;
597636

598-
// Wait until the byte is received
599637
timeout = FLAG_TIMEOUT;
600-
while (__HAL_I2C_GET_FLAG(handle, I2C_FLAG_RXNE) == RESET) {
638+
while (!__HAL_I2C_GET_FLAG(handle, I2C_FLAG_RXNE)) {
601639
if ((timeout--) == 0) {
602640
return -1;
603641
}
604642
}
605643

606-
return (int)i2c->RXDR;
644+
/* Then Get Byte */
645+
data = handle->Instance->RXDR;
646+
647+
if (last) {
648+
/* Disable Address Acknowledge */
649+
handle->Instance->CR2 |= I2C_CR2_NACK;
650+
}
651+
652+
return data;
607653
}
608654

609655
int i2c_byte_write(i2c_t *obj, int data) {
610656
struct i2c_s *obj_s = I2C_S(obj);
611-
I2C_TypeDef *i2c = (I2C_TypeDef *)obj_s->i2c;
612657
I2C_HandleTypeDef *handle = &(obj_s->handle);
613-
int timeout;
614-
615-
// Wait until the previous byte is transmitted
616-
timeout = FLAG_TIMEOUT;
617-
while (__HAL_I2C_GET_FLAG(handle, I2C_FLAG_TXIS) == RESET) {
618-
if ((timeout--) == 0) {
619-
return 0;
658+
int timeout = FLAG_TIMEOUT;
659+
uint32_t tmpreg = handle->Instance->CR2;
660+
#if DEVICE_I2CSLAVE
661+
if (obj_s->slave) {
662+
return i2c_slave_write(obj, (char *) &data, 1);
663+
}
664+
#endif
665+
if (obj_s->pending_start) {
666+
obj_s->pending_start = 0;
667+
//* First byte after the start is the address */
668+
tmpreg |= (uint32_t)((uint32_t)data & I2C_CR2_SADD);
669+
if (data & 0x01) {
670+
tmpreg |= I2C_CR2_START | I2C_CR2_RD_WRN;
671+
} else {
672+
tmpreg |= I2C_CR2_START;
673+
tmpreg &= ~I2C_CR2_RD_WRN;
674+
}
675+
/* Disable reload first to use it later */
676+
tmpreg &= ~I2C_CR2_RELOAD;
677+
/* Disable Autoend */
678+
tmpreg &= ~I2C_CR2_AUTOEND;
679+
/* Do not set any transfer size for now */
680+
tmpreg |= (I2C_CR2_NBYTES & (1 << 16));
681+
/* Set the prepared configuration */
682+
handle->Instance->CR2 = tmpreg;
683+
} else {
684+
/* Set the prepared configuration */
685+
tmpreg = handle->Instance->CR2;
686+
687+
/* Then send data when there's room in the TX fifo */
688+
if ((tmpreg & I2C_CR2_RELOAD) != 0) {
689+
while (!__HAL_I2C_GET_FLAG(handle, I2C_FLAG_TCR)) {
690+
if ((timeout--) == 0) {
691+
DEBUG_PRINTF("timeout in byte_write\r\n");
692+
return 2;
693+
}
694+
}
620695
}
696+
/* Enable reload mode as we don't know how many bytes will eb sent */
697+
tmpreg |= I2C_CR2_RELOAD;
698+
/* Set transfer size to 1 */
699+
tmpreg |= (I2C_CR2_NBYTES & (1 << 16));
700+
/* Set the prepared configuration */
701+
handle->Instance->CR2 = tmpreg;
702+
/* Prepare next write */
703+
timeout = FLAG_TIMEOUT;
704+
while (!__HAL_I2C_GET_FLAG(handle, I2C_FLAG_TXE)) {
705+
if ((timeout--) == 0) {
706+
return 2;
707+
}
708+
}
709+
/* Write byte */
710+
handle->Instance->TXDR = data;
621711
}
622712

623-
i2c->TXDR = (uint8_t)data;
624-
625713
return 1;
626714
}
627715
#endif //I2C_IP_VERSION_V2
628716

629-
void i2c_reset(i2c_t *obj) {
630-
struct i2c_s *obj_s = I2C_S(obj);
631-
/* As recommended in i2c_api.h, mainly send stop */
632-
i2c_stop(obj);
633-
/* then re-init */
634-
i2c_init(obj, obj_s->sda, obj_s->scl);
635-
}
636-
637717
/*
638718
* SYNC APIS
639719
*/

0 commit comments

Comments
 (0)