diff --git a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/device.h b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/device.h index af26f8f36d..57a7aa227d 100644 --- a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/device.h +++ b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/device.h @@ -42,10 +42,10 @@ #define DEVICE_SERIAL 1 #define DEVICE_I2C 1 -#define DEVICE_I2CSLAVE 0 // Not yet supported +#define DEVICE_I2CSLAVE 1 #define DEVICE_SPI 1 -#define DEVICE_SPISLAVE 0 // Not yet supported +#define DEVICE_SPISLAVE 1 #define DEVICE_RTC 1 diff --git a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/i2c_api.c b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/i2c_api.c index 8725e17b52..68c032d323 100644 --- a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/i2c_api.c +++ b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/i2c_api.c @@ -181,7 +181,7 @@ int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) { I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c); int timeout; int count; - + i2c_start(obj); // Send slave address for write @@ -245,7 +245,7 @@ int i2c_byte_write(i2c_t *obj, int data) { I2C_SendData(i2c, (uint8_t)data); // Wait until the byte is transmitted - timeout = FLAG_TIMEOUT; + timeout = FLAG_TIMEOUT; while ((I2C_GetFlagStatus(i2c, I2C_FLAG_TXE) == RESET) && (I2C_GetFlagStatus(i2c, I2C_FLAG_BTF) == RESET)) { timeout--; @@ -295,7 +295,46 @@ void i2c_slave_mode(i2c_t *obj, int enable_slave) { #define WriteAddressed 3 // the master is writing to this slave (slave = receiver) int i2c_slave_receive(i2c_t *obj) { - return (0); + int retValue = NoData; + uint32_t event; + I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c); + + event = I2C_GetLastEvent( i2c ); + if(event != 0) + { + switch(event){ + case I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED: + retValue = WriteAddressed; + break; + case I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED: + retValue = ReadAddressed; + break; + case I2C_EVENT_SLAVE_GENERALCALLADDRESS_MATCHED: + retValue = WriteGeneral; + break; + default: + retValue = NoData; + break; + } + + // clear ADDR + if((retValue == WriteAddressed) || (retValue == ReadAddressed)){ + // read SR to clear ADDR flag + i2c->SR1; + i2c->SR2; + } + // clear stopf + if(I2C_GetFlagStatus(i2c, I2C_FLAG_STOPF) == SET) { + // read SR1 and write CR1 to clear STOP flag + i2c->SR1; + I2C_Cmd(i2c, ENABLE); + } + // clear AF + if(I2C_GetFlagStatus(i2c, I2C_FLAG_AF) == SET) { + I2C_ClearFlag(i2c, I2C_FLAG_AF); + } + } + return(retValue); } int i2c_slave_read(i2c_t *obj, char *data, int length) { diff --git a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/spi_api.c b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/spi_api.c index 9099ff96eb..d7f40e9902 100644 --- a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/spi_api.c +++ b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/spi_api.c @@ -125,7 +125,7 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel } else { // Slave pinmap_pinout(ssel, PinMap_SPI_SSEL); obj->mode = SPI_Mode_Slave; - obj->nss = SPI_NSS_Soft; + obj->nss = SPI_NSS_Hard; } init_spi(obj); diff --git a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F401RE/device.h b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F401RE/device.h index 302ed7582d..57a7aa227d 100644 --- a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F401RE/device.h +++ b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F401RE/device.h @@ -42,10 +42,10 @@ #define DEVICE_SERIAL 1 #define DEVICE_I2C 1 -#define DEVICE_I2CSLAVE 0 // Not supported yet +#define DEVICE_I2CSLAVE 1 #define DEVICE_SPI 1 -#define DEVICE_SPISLAVE 0 // Not supported yet +#define DEVICE_SPISLAVE 1 #define DEVICE_RTC 1 diff --git a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F401RE/i2c_api.c b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F401RE/i2c_api.c index bb6fc1443d..9f0d655f50 100644 --- a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F401RE/i2c_api.c +++ b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F401RE/i2c_api.c @@ -93,6 +93,9 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) { // I2C configuration i2c_frequency(obj, 100000); // 100 kHz per default + + // I2C master by default + obj->slave = 0; } void i2c_frequency(i2c_t *obj, int hz) { @@ -109,6 +112,10 @@ void i2c_frequency(i2c_t *obj, int hz) { I2cHandle.Init.OwnAddress1 = 0; I2cHandle.Init.OwnAddress2 = 0; HAL_I2C_Init(&I2cHandle); + if(obj->slave) { + /* Enable Address Acknowledge */ + I2cHandle.Instance->CR1 |= I2C_CR1_ACK; + } } else { error("I2C error: frequency setting failed (max 400kHz)."); @@ -233,7 +240,7 @@ void i2c_reset(i2c_t *obj) { void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask) { I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c); - uint16_t tmpreg; + uint16_t tmpreg = 0; // Get the old register value tmpreg = i2c->OAR1; @@ -246,7 +253,12 @@ void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask) { } void i2c_slave_mode(i2c_t *obj, int enable_slave) { - // Nothing to do + I2cHandle.Instance = (I2C_TypeDef *)(obj->i2c); + if(enable_slave) { + obj->slave = 1; + /* Enable Address Acknowledge */ + I2cHandle.Instance->CR1 |= I2C_CR1_ACK; + } } // See I2CSlave.h @@ -256,34 +268,140 @@ void i2c_slave_mode(i2c_t *obj, int enable_slave) { #define WriteAddressed 3 // the master is writing to this slave (slave = receiver) int i2c_slave_receive(i2c_t *obj) { - // TO BE DONE - return(0); + int retValue = NoData; + + if(__HAL_I2C_GET_FLAG(&I2cHandle, I2C_FLAG_BUSY) == 1) { + if(__HAL_I2C_GET_FLAG(&I2cHandle, I2C_FLAG_ADDR) == 1) { + if(__HAL_I2C_GET_FLAG(&I2cHandle, I2C_FLAG_TRA) == 1) + retValue = ReadAddressed; + else + retValue = WriteAddressed; + + __HAL_I2C_CLEAR_FLAG(&I2cHandle, I2C_FLAG_ADDR); + } + } + + return(retValue); } int i2c_slave_read(i2c_t *obj, char *data, int length) { + uint32_t Timeout; + int size = 0; if (length == 0) return 0; I2cHandle.Instance = (I2C_TypeDef *)(obj->i2c); - // Reception process with 5 seconds timeout - if (HAL_I2C_Slave_Receive(&I2cHandle, (uint8_t *)data, length, 5000) != HAL_OK) { - return 0; // Error + while(length > 0) + { + /* Wait until RXNE flag is set */ + // Wait until the byte is received + Timeout = FLAG_TIMEOUT; + while (__HAL_I2C_GET_FLAG(&I2cHandle, I2C_FLAG_RXNE) == RESET) { + Timeout--; + if (Timeout == 0) { + return 0; + } + } + + /* Read data from DR */ + (*data++) = I2cHandle.Instance->DR; + length--; + size++; + + if((__HAL_I2C_GET_FLAG(&I2cHandle, I2C_FLAG_BTF) == SET) && (length != 0)){ + /* Read data from DR */ + (*data++) = I2cHandle.Instance->DR; + length--; + size++; + } } - return length; + /* Wait until STOP flag is set */ + Timeout = FLAG_TIMEOUT; + while (__HAL_I2C_GET_FLAG(&I2cHandle, I2C_FLAG_STOPF) == RESET) { + Timeout--; + if (Timeout == 0) { + return 0; + } + } + + /* Clear STOP flag */ + __HAL_I2C_CLEAR_STOPFLAG(&I2cHandle); + + /* Wait until BUSY flag is reset */ + Timeout = FLAG_TIMEOUT; + while (__HAL_I2C_GET_FLAG(&I2cHandle, I2C_FLAG_BUSY) == SET) { + Timeout--; + if (Timeout == 0) { + return 0; + } + } + + return size; } int i2c_slave_write(i2c_t *obj, const char *data, int length) { + uint32_t Timeout; + int size = 0; if (length == 0) return 0; I2cHandle.Instance = (I2C_TypeDef *)(obj->i2c); - // Transmission process with 5 seconds timeout - if (HAL_I2C_Slave_Transmit(&I2cHandle, (uint8_t *)data, length, 5000) != HAL_OK) { - return 0; // Error + while(length > 0) + { + /* Wait until TXE flag is set */ + Timeout = FLAG_TIMEOUT; + while (__HAL_I2C_GET_FLAG(&I2cHandle, I2C_FLAG_TXE) == RESET) { + Timeout--; + if (Timeout == 0) { + return 0; + } + } + + + /* Write data to DR */ + I2cHandle.Instance->DR = (*data++); + length--; + size++; + + if((__HAL_I2C_GET_FLAG(&I2cHandle, I2C_FLAG_BTF) == SET) && (length != 0)) + { + /* Write data to DR */ + I2cHandle.Instance->DR = (*data++); + length--; + size++; + } + } + + /* Wait until AF flag is set */ + Timeout = FLAG_TIMEOUT; + while (__HAL_I2C_GET_FLAG(&I2cHandle, I2C_FLAG_AF) == RESET) { + Timeout--; + if (Timeout == 0) { + return 0; + } + } + + + /* Clear AF flag */ + __HAL_I2C_CLEAR_FLAG(&I2cHandle, I2C_FLAG_AF); + + + /* Wait until BUSY flag is reset */ + Timeout = FLAG_TIMEOUT; + while (__HAL_I2C_GET_FLAG(&I2cHandle, I2C_FLAG_BUSY) == SET) { + Timeout--; + if (Timeout == 0) { + return 0; + } } - return length; + I2cHandle.State = HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(&I2cHandle); + + return size; } diff --git a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F401RE/objects.h b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F401RE/objects.h index a1346adf1e..bca04d3d40 100644 --- a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F401RE/objects.h +++ b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F401RE/objects.h @@ -80,6 +80,7 @@ struct spi_s { struct i2c_s { I2CName i2c; + uint32_t slave; }; struct pwmout_s { diff --git a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F401RE/spi_api.c b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F401RE/spi_api.c index bf94d48fe3..52c271499b 100644 --- a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F401RE/spi_api.c +++ b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F401RE/spi_api.c @@ -256,7 +256,7 @@ int spi_master_write(spi_t *obj, int value) { } int spi_slave_receive(spi_t *obj) { - return (!ssp_busy(obj)) ? (1) : (0); + return (ssp_readable(obj) && !ssp_busy(obj)) ? (1) : (0); }; int spi_slave_read(spi_t *obj) {