Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-src by
Revision 197:36a724675865, committed 2014-05-19
- Comitter:
- mbed_official
- Date:
- Mon May 19 11:00:07 2014 +0100
- Parent:
- 196:fdfa63dee410
- Child:
- 198:322bca33c29c
- Commit message:
- Synchronized with git revision ffcaadfc684a5938533d664b7ef3aa138d51dafe
Full URL: https://github.com/mbedmicro/mbed/commit/ffcaadfc684a5938533d664b7ef3aa138d51dafe/
[NUCLEO_F302R8] Add I2C slave, enhance I2C master
Changed in this revision
--- a/targets/hal/TARGET_STM/TARGET_NUCLEO_F030R8/i2c_api.c Mon May 19 08:45:07 2014 +0100
+++ b/targets/hal/TARGET_STM/TARGET_NUCLEO_F030R8/i2c_api.c Mon May 19 11:00:07 2014 +0100
@@ -178,12 +178,13 @@
int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) {
I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
int count;
+ int timeout;
int value;
if (length == 0) return 0;
// Configure slave address, nbytes, reload, end mode and start or stop generation
- I2C_TransferHandling(i2c, address, length, I2C_AutoEnd_Mode, I2C_Generate_Start_Read);
+ I2C_TransferHandling(i2c, address, length, I2C_SoftEnd_Mode, I2C_Generate_Start_Read);
// Read all bytes
for (count = 0; count < length; count++) {
@@ -191,33 +192,40 @@
data[count] = (char)value;
}
+ timeout = FLAG_TIMEOUT;
+ while(!I2C_GetFlagStatus(i2c, I2C_FLAG_TC)) {
+ timeout--;
+ if (timeout == 0) return 0;
+ }
+
+ if(stop) i2c_stop(obj);
+
return length;
}
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 timeout;
int count;
if (length == 0) return 0;
- // Configure slave address, nbytes, reload, end mode and start or stop generation
- if (stop) {
- I2C_TransferHandling(i2c, address, length, I2C_AutoEnd_Mode, I2C_Generate_Start_Write);
-
- }
- else {
+ // Configure slave address, nbytes, reload, end mode and start generation
I2C_TransferHandling(i2c, address, length, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);
- }
// Write all bytes
for (count = 0; count < length; count++) {
- if (i2c_byte_write(obj, data[count]) != 1) {
- if(!stop) i2c_stop(obj);
- return 0;
+ i2c_byte_write(obj, data[count]);
}
+
+ timeout = FLAG_TIMEOUT;
+ while(!I2C_GetFlagStatus(i2c, I2C_FLAG_TC)) {
+ timeout--;
+ if (timeout == 0) return 0;
}
+ if(stop) i2c_stop(obj);
+
return count;
}
--- a/targets/hal/TARGET_STM/TARGET_NUCLEO_F302R8/device.h Mon May 19 08:45:07 2014 +0100 +++ b/targets/hal/TARGET_STM/TARGET_NUCLEO_F302R8/device.h Mon May 19 11:00:07 2014 +0100 @@ -42,7 +42,7 @@ #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
--- a/targets/hal/TARGET_STM/TARGET_NUCLEO_F302R8/i2c_api.c Mon May 19 08:45:07 2014 +0100
+++ b/targets/hal/TARGET_STM/TARGET_NUCLEO_F302R8/i2c_api.c Mon May 19 11:00:07 2014 +0100
@@ -76,6 +76,7 @@
// Enable I2C clock
if (obj->i2c == I2C_1) {
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
+ RCC_I2CCLKConfig(RCC_I2C1CLK_SYSCLK);
}
if (obj->i2c == I2C_2) {
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
@@ -113,35 +114,66 @@
* Fast Mode (up to 400 kHz)
* Fast Mode Plus (up to 1 MHz)
Below values obtained with:
- - I2C clock source = 8 MHz (HSI clock per default)
+ - I2C clock source = 64 MHz (System Clock w/ HSI) or 72 (System Clock w/ HSE)
- Analog filter delay = ON
- Digital filter coefficient = 0
- Rise time = 100 ns
- Fall time = 10ns
*/
- switch (hz) {
- case 100000:
- tim = 0x00201D2B; // Standard mode
+ if (SystemCoreClock == 64000000) {
+ switch (hz) {
+ case 100000:
+ tim = 0x60302730; // Standard mode
+ break;
+ case 200000:
+ tim = 0x00C07AB3; // Fast Mode
+ break;
+ case 400000:
+ tim = 0x00C0216C; // Fast Mode
break;
- case 200000:
- tim = 0x0010021E; // Fast Mode
+ case 1000000:
+ tim = 0x00900B22; // Fast Mode Plus
+ // Enable the Fast Mode Plus capability
+ if (obj->i2c == I2C_1) {
+ SYSCFG_I2CFastModePlusConfig(SYSCFG_I2CFastModePlus_I2C1, ENABLE);
+ }
+ if (obj->i2c == I2C_2) {
+ SYSCFG_I2CFastModePlusConfig(SYSCFG_I2CFastModePlus_I2C2, ENABLE);
+ }
break;
- case 400000:
- tim = 0x0010020A; // Fast Mode
+ default:
+ error("Only 100kHz, 200kHz, 400kHz and 1MHz I2C frequencies are supported.");
break;
- case 1000000:
- tim = 0x00100001; // Fast Mode Plus
- // Enable the Fast Mode Plus capability
- if (obj->i2c == I2C_1) {
- SYSCFG_I2CFastModePlusConfig(SYSCFG_I2CFastModePlus_I2C1, ENABLE);
- }
- if (obj->i2c == I2C_2) {
- SYSCFG_I2CFastModePlusConfig(SYSCFG_I2CFastModePlus_I2C2, ENABLE);
- }
- break;
- default:
- error("Only 100kHz, 200kHz, 400kHz and 1MHz I2C frequencies are supported.");
- break;
+ }
+ }
+ else if (SystemCoreClock == 72000000) {
+ switch (hz) {
+ case 100000:
+ tim = 0x10C08DCF; // Standard mode
+ break;
+ case 200000:
+ tim = 0xA010031A; // Fast Mode
+ break;
+ case 400000:
+ tim = 0x00E0257A; // Fast Mode
+ break;
+ case 1000000:
+ tim = 0x00A00D26; // Fast Mode Plus
+ // Enable the Fast Mode Plus capability
+ if (obj->i2c == I2C_1) {
+ SYSCFG_I2CFastModePlusConfig(SYSCFG_I2CFastModePlus_I2C1, ENABLE);
+ }
+ if (obj->i2c == I2C_2) {
+ SYSCFG_I2CFastModePlusConfig(SYSCFG_I2CFastModePlus_I2C2, ENABLE);
+ }
+ break;
+ default:
+ error("Only 100kHz, 200kHz, 400kHz and 1MHz I2C frequencies are supported.");
+ break;
+ }
+ }
+ else {
+ error("System clock setting is not supported.");
}
// I2C configuration
@@ -184,15 +216,17 @@
return 0;
}
+
int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) {
I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
int count;
+ int timeout;
int value;
if (length == 0) return 0;
// Configure slave address, nbytes, reload, end mode and start or stop generation
- I2C_TransferHandling(i2c, address, length, I2C_AutoEnd_Mode, I2C_Generate_Start_Read);
+ I2C_TransferHandling(i2c, address, length, I2C_SoftEnd_Mode, I2C_Generate_Start_Read);
// Read all bytes
for (count = 0; count < length; count++) {
@@ -200,48 +234,40 @@
data[count] = (char)value;
}
+ timeout = FLAG_TIMEOUT;
+ while(!I2C_GetFlagStatus(i2c, I2C_FLAG_TC)) {
+ timeout--;
+ if (timeout == 0) return 0;
+ }
+
+ if(stop) i2c_stop(obj);
+
return length;
}
+
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 timeout;
int count;
if (length == 0) return 0;
- // [TODO] The stop is always sent even with I2C_SoftEnd_Mode. To be corrected.
-
- // Configure slave address, nbytes, reload, end mode and start or stop generation
- //if (stop) {
- I2C_TransferHandling(i2c, address, length, I2C_AutoEnd_Mode, I2C_Generate_Start_Write);
- //}
- //else {
- // I2C_TransferHandling(i2c, address, length, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);
- //}
+ // Configure slave address, nbytes, reload, end mode and start generation
+ I2C_TransferHandling(i2c, address, length, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);
// Write all bytes
for (count = 0; count < length; count++) {
- if (i2c_byte_write(obj, data[count]) != 1) {
- i2c_stop(obj);
- return 0;
- }
+ i2c_byte_write(obj, data[count]);
}
- /*
- if (stop) {
- // Wait until STOPF flag is set
- timeout = LONG_TIMEOUT;
- while (I2C_GetFlagStatus(i2c, I2C_ISR_STOPF) == RESET) {
- timeout--;
- if (timeout == 0) {
- return 0;
- }
- }
- // Clear STOPF flag
- I2C_ClearFlag(i2c, I2C_ICR_STOPCF);
+ timeout = FLAG_TIMEOUT;
+ while(!I2C_GetFlagStatus(i2c, I2C_FLAG_TC)) {
+ timeout--;
+ if (timeout == 0) return 0;
}
- */
+
+ if(stop) i2c_stop(obj);
return count;
}
@@ -304,6 +330,9 @@
I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
uint16_t tmpreg;
+ // reset own address enable
+ i2c->OAR1 &=~ I2C_OAR1_OA1EN;
+
// Get the old register value
tmpreg = i2c->OAR1;
// Reset address bits
@@ -311,7 +340,7 @@
// Set new address
tmpreg |= (uint16_t)((uint16_t)address & (uint16_t)0x00FE); // 7-bits
// Store the new register value
- i2c->OAR1 = tmpreg;
+ i2c->OAR1 = tmpreg | I2C_OAR1_OA1EN;
}
void i2c_slave_mode(i2c_t *obj, int enable_slave) {
@@ -325,8 +354,21 @@
#define WriteAddressed 3 // the master is writing to this slave (slave = receiver)
int i2c_slave_receive(i2c_t *obj) {
- // TO BE DONE
- return (0);
+ I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
+ int event = NoData;
+
+ if(I2C_GetFlagStatus(i2c, I2C_ISR_BUSY) == SET) {
+ if(I2C_GetFlagStatus(i2c, I2C_ISR_ADDR) == SET) {
+ // Check direction
+ if (I2C_GetFlagStatus(i2c, I2C_ISR_DIR) == SET) {
+ event = ReadAddressed;
+ }
+ else event = WriteAddressed;
+ // Clear adress match flag to generate an acknowledge
+ i2c->ICR |= I2C_ICR_ADDRCF;
+ }
+ }
+ return event;
}
int i2c_slave_read(i2c_t *obj, char *data, int length) {
