Skip to content

[NUCLEO_F302R8] Add I2C slave, enhance I2C master #310

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

Merged
merged 3 commits into from
May 19, 2014
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
Original file line number Diff line number Diff line change
Expand Up @@ -178,46 +178,54 @@ inline int i2c_stop(i2c_t *obj) {
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++) {
value = i2c_byte_read(obj, 0);
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;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
142 changes: 92 additions & 50 deletions libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F302R8/i2c_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
// 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);
Expand Down Expand Up @@ -113,35 +114,66 @@ void i2c_frequency(i2c_t *obj, int hz) {
* 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 = 0x0010021E; // Fast Mode
case 200000:
tim = 0x00C07AB3; // Fast Mode
break;
case 400000:
tim = 0x0010020A; // Fast Mode
case 400000:
tim = 0x00C0216C; // Fast Mode
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);
}
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;
default:
error("Only 100kHz, 200kHz, 400kHz and 1MHz I2C frequencies are supported.");
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
Expand Down Expand Up @@ -184,64 +216,58 @@ inline int i2c_stop(i2c_t *obj) {
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++) {
value = i2c_byte_read(obj, 0);
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;
}
Expand Down Expand Up @@ -304,14 +330,17 @@ 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;

// reset own address enable
i2c->OAR1 &=~ I2C_OAR1_OA1EN;

// Get the old register value
tmpreg = i2c->OAR1;
// Reset address bits
tmpreg &= 0xFC00;
// 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) {
Expand All @@ -325,8 +354,21 @@ 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);
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) {
Expand Down