Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev stm i2c v2 unitary functions #3488

Merged
merged 7 commits into from
Jan 9, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 6 additions & 12 deletions features/unsupported/tests/mbed/i2c_master_slave/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
#error [NOT_SUPPORTED] Target has only one I2C instance
#endif

#define ADDR (0xA0)
#define ADDR (0x80)
#define FREQ 100000

// ********************************************************
Expand Down Expand Up @@ -89,11 +89,8 @@ int main()
master.start();
master.write(ADDR);
master.write(sent);
if(slave.receive() != I2CSlave::WriteAddressed)
{
notify_completion(false);
return 1;
}
while(slave.receive() != I2CSlave::WriteAddressed);

slave.read(&received, 1);
if(sent != received)
{
Expand All @@ -105,14 +102,11 @@ int main()
// Second transfer: slave to master
master.start();
master.write(ADDR | 1);
if(slave.receive() != I2CSlave::ReadAddressed)
{
notify_completion(false);
return 1;
}
while(slave.receive() != I2CSlave::ReadAddressed);

slave.write(received);
received = master.read(0);
slave.stop();
master.stop();
notify_completion(received == sent);
}

Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ I2C master(D14, D15); // I2C_SDA, I2C_SCL
defined (TARGET_DISCO_F429ZI) || \
defined (TARGET_NUCLEO_F767ZI) || \
defined (TARGET_NUCLEO_L053R8) || \
defined (TARGET_NUCLEO_L073RZ) || \
defined (TARGET_NUCLEO_L152RE) || \
defined (TARGET_NUCLEO_L476RG)
I2CSlave slave(PB_11, PB_10);
Expand Down
1 change: 1 addition & 0 deletions targets/TARGET_STM/TARGET_STM32F0/common_objects.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ struct i2c_s {
IRQn_Type error_i2cIRQ;
uint32_t XferOperation;
volatile uint8_t event;
volatile int pending_start;
#if DEVICE_I2CSLAVE
uint8_t slave;
volatile uint8_t pending_slave_tx_master_rx;
Expand Down
1 change: 1 addition & 0 deletions targets/TARGET_STM/TARGET_STM32F3/common_objects.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ struct i2c_s {
IRQn_Type error_i2cIRQ;
uint32_t XferOperation;
volatile uint8_t event;
volatile int pending_start;
#if DEVICE_I2CSLAVE
uint8_t slave;
volatile uint8_t pending_slave_tx_master_rx;
Expand Down
1 change: 1 addition & 0 deletions targets/TARGET_STM/TARGET_STM32F7/common_objects.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ struct i2c_s {
IRQn_Type error_i2cIRQ;
uint32_t XferOperation;
volatile uint8_t event;
volatile int pending_start;
#if DEVICE_I2CSLAVE
uint8_t slave;
volatile uint8_t pending_slave_tx_master_rx;
Expand Down
1 change: 1 addition & 0 deletions targets/TARGET_STM/TARGET_STM32L0/common_objects.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ struct i2c_s {
IRQn_Type error_i2cIRQ;
uint32_t XferOperation;
volatile uint8_t event;
volatile int pending_start;
#if DEVICE_I2CSLAVE
uint8_t slave;
volatile uint8_t pending_slave_tx_master_rx;
Expand Down
1 change: 1 addition & 0 deletions targets/TARGET_STM/TARGET_STM32L4/common_objects.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ struct i2c_s {
IRQn_Type error_i2cIRQ;
uint32_t XferOperation;
volatile uint8_t event;
volatile int pending_start;
#if DEVICE_I2CSLAVE
uint8_t slave;
volatile uint8_t pending_slave_tx_master_rx;
Expand Down
178 changes: 129 additions & 49 deletions targets/TARGET_STM/i2c_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,9 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
// I2C Xfer operation init
obj_s->event = 0;
obj_s->XferOperation = I2C_FIRST_AND_LAST_FRAME;
#ifdef I2C_IP_VERSION_V2
obj_s->pending_start = 0;
#endif
}

void i2c_frequency(i2c_t *obj, int hz)
Expand Down Expand Up @@ -440,6 +443,14 @@ i2c_t *get_i2c_obj(I2C_HandleTypeDef *hi2c){
return (obj);
}

void i2c_reset(i2c_t *obj) {
struct i2c_s *obj_s = I2C_S(obj);
/* As recommended in i2c_api.h, mainly send stop */
i2c_stop(obj);
/* then re-init */
i2c_init(obj, obj_s->sda, obj_s->scl);
}

/*
* UNITARY APIS.
* For very basic operations, direct registers access is needed
Expand Down Expand Up @@ -535,7 +546,7 @@ int i2c_byte_write(i2c_t *obj, int data) {
(__HAL_I2C_GET_FLAG(handle, I2C_FLAG_BTF) == RESET) &&
(__HAL_I2C_GET_FLAG(handle, I2C_FLAG_ADDR) == RESET)) {
if ((timeout--) == 0) {
return 0;
return 2;
}
}

Expand All @@ -548,92 +559,161 @@ int i2c_byte_write(i2c_t *obj, int data) {
}
#endif //I2C_IP_VERSION_V1
#ifdef I2C_IP_VERSION_V2

int i2c_start(i2c_t *obj) {
struct i2c_s *obj_s = I2C_S(obj);
I2C_HandleTypeDef *handle = &(obj_s->handle);
I2C_TypeDef *i2c = (I2C_TypeDef *)obj_s->i2c;
int timeout;

// Clear Acknowledge failure flag
__HAL_I2C_CLEAR_FLAG(handle, I2C_FLAG_AF);
/* This I2C IP doesn't */
obj_s->pending_start = 1;
return 0;
}

// Wait the STOP condition has been previously correctly sent
timeout = FLAG_TIMEOUT;
while ((i2c->CR2 & I2C_CR2_STOP) == I2C_CR2_STOP){
if ((timeout--) == 0) {
return 1;
}
int i2c_stop(i2c_t *obj) {
struct i2c_s *obj_s = I2C_S(obj);
I2C_HandleTypeDef *handle = &(obj_s->handle);
int timeout = FLAG_TIMEOUT;
#if DEVICE_I2CSLAVE
if (obj_s->slave) {
/* re-init slave when stop is requested */
i2c_init(obj, obj_s->sda, obj_s->scl);
return 0;
}
#endif
// Disable reload mode
handle->Instance->CR2 &= (uint32_t)~I2C_CR2_RELOAD;
// Generate the STOP condition
handle->Instance->CR2 |= I2C_CR2_STOP;

// Generate the START condition
i2c->CR2 |= I2C_CR2_START;

// Wait the START condition has been correctly sent
timeout = FLAG_TIMEOUT;
while (__HAL_I2C_GET_FLAG(handle, I2C_FLAG_BUSY) == RESET) {
while (!__HAL_I2C_GET_FLAG(handle, I2C_FLAG_STOPF)) {
if ((timeout--) == 0) {
return 1;
return I2C_ERROR_BUS_BUSY;
}
}

return 0;
}
/* Clear STOP Flag */
__HAL_I2C_CLEAR_FLAG(handle, I2C_FLAG_STOPF);

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

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

return 0;
}

int i2c_byte_read(i2c_t *obj, int last) {
struct i2c_s *obj_s = I2C_S(obj);
I2C_TypeDef *i2c = (I2C_TypeDef *)obj_s->i2c;
I2C_HandleTypeDef *handle = &(obj_s->handle);
int timeout;
int timeout = FLAG_TIMEOUT;
uint32_t tmpreg = handle->Instance->CR2;
char data;
#if DEVICE_I2CSLAVE
if (obj_s->slave) {
return i2c_slave_read(obj, &data, 1);
}
#endif
/* Then send data when there's room in the TX fifo */
if ((tmpreg & I2C_CR2_RELOAD) != 0) {
while (!__HAL_I2C_GET_FLAG(handle, I2C_FLAG_TCR)) {
if ((timeout--) == 0) {
DEBUG_PRINTF("timeout in byte_read\r\n");
return -1;
}
}
}

/* Enable reload mode as we don't know how many bytes will eb sent */
handle->Instance->CR2 |= I2C_CR2_RELOAD;
/* Set transfer size to 1 */
handle->Instance->CR2 |= (I2C_CR2_NBYTES & (1 << 16));
/* Set the prepared configuration */
handle->Instance->CR2 = tmpreg;

// Wait until the byte is received
timeout = FLAG_TIMEOUT;
while (__HAL_I2C_GET_FLAG(handle, I2C_FLAG_RXNE) == RESET) {
while (!__HAL_I2C_GET_FLAG(handle, I2C_FLAG_RXNE)) {
if ((timeout--) == 0) {
return -1;
}
}

return (int)i2c->RXDR;
/* Then Get Byte */
data = handle->Instance->RXDR;

if (last) {
/* Disable Address Acknowledge */
handle->Instance->CR2 |= I2C_CR2_NACK;
}

return data;
}

int i2c_byte_write(i2c_t *obj, int data) {
struct i2c_s *obj_s = I2C_S(obj);
I2C_TypeDef *i2c = (I2C_TypeDef *)obj_s->i2c;
I2C_HandleTypeDef *handle = &(obj_s->handle);
int timeout;

// Wait until the previous byte is transmitted
timeout = FLAG_TIMEOUT;
while (__HAL_I2C_GET_FLAG(handle, I2C_FLAG_TXIS) == RESET) {
if ((timeout--) == 0) {
return 0;
int timeout = FLAG_TIMEOUT;
uint32_t tmpreg = handle->Instance->CR2;
#if DEVICE_I2CSLAVE
if (obj_s->slave) {
return i2c_slave_write(obj, (char *) &data, 1);
}
#endif
if (obj_s->pending_start) {
obj_s->pending_start = 0;
//* First byte after the start is the address */
tmpreg |= (uint32_t)((uint32_t)data & I2C_CR2_SADD);
if (data & 0x01) {
tmpreg |= I2C_CR2_START | I2C_CR2_RD_WRN;
} else {
tmpreg |= I2C_CR2_START;
tmpreg &= ~I2C_CR2_RD_WRN;
}
/* Disable reload first to use it later */
tmpreg &= ~I2C_CR2_RELOAD;
/* Disable Autoend */
tmpreg &= ~I2C_CR2_AUTOEND;
/* Do not set any transfer size for now */
tmpreg |= (I2C_CR2_NBYTES & (1 << 16));
/* Set the prepared configuration */
handle->Instance->CR2 = tmpreg;
} else {
/* Set the prepared configuration */
tmpreg = handle->Instance->CR2;

/* Then send data when there's room in the TX fifo */
if ((tmpreg & I2C_CR2_RELOAD) != 0) {
while (!__HAL_I2C_GET_FLAG(handle, I2C_FLAG_TCR)) {
if ((timeout--) == 0) {
DEBUG_PRINTF("timeout in byte_write\r\n");
return 2;
}
}
}
/* Enable reload mode as we don't know how many bytes will eb sent */
tmpreg |= I2C_CR2_RELOAD;
/* Set transfer size to 1 */
tmpreg |= (I2C_CR2_NBYTES & (1 << 16));
/* Set the prepared configuration */
handle->Instance->CR2 = tmpreg;
/* Prepare next write */
timeout = FLAG_TIMEOUT;
while (!__HAL_I2C_GET_FLAG(handle, I2C_FLAG_TXE)) {
if ((timeout--) == 0) {
return 2;
}
}
/* Write byte */
handle->Instance->TXDR = data;
}

i2c->TXDR = (uint8_t)data;

return 1;
}
#endif //I2C_IP_VERSION_V2

void i2c_reset(i2c_t *obj) {
struct i2c_s *obj_s = I2C_S(obj);
/* As recommended in i2c_api.h, mainly send stop */
i2c_stop(obj);
/* then re-init */
i2c_init(obj, obj_s->sda, obj_s->scl);
}

/*
* SYNC APIS
*/
Expand Down