diff --git a/hal/inc/hal_dynalib_i2c.h b/hal/inc/hal_dynalib_i2c.h index 73a10fe02d..39a440f462 100644 --- a/hal/inc/hal_dynalib_i2c.h +++ b/hal/inc/hal_dynalib_i2c.h @@ -80,6 +80,7 @@ DYNALIB_FN(BASE_IDX + 13, hal_i2c, HAL_I2C_Is_Enabled, bool(HAL_I2C_Interface, v DYNALIB_FN(BASE_IDX + 14, hal_i2c, HAL_I2C_Set_Callback_On_Receive, void(HAL_I2C_Interface, void(*)(int), void*)) DYNALIB_FN(BASE_IDX + 15, hal_i2c, HAL_I2C_Set_Callback_On_Request, void(HAL_I2C_Interface, void(*)(void), void*)) DYNALIB_FN(BASE_IDX + 16, hal_i2c, HAL_I2C_Init, void(HAL_I2C_Interface, void*)) +DYNALIB_FN(BASE_IDX + 17, hal_i2c, HAL_I2C_Reset, uint8_t(HAL_I2C_Interface, uint32_t, void*)) DYNALIB_END(hal_i2c) diff --git a/hal/inc/i2c_hal.h b/hal/inc/i2c_hal.h index 3463620894..0468d983bb 100644 --- a/hal/inc/i2c_hal.h +++ b/hal/inc/i2c_hal.h @@ -74,6 +74,7 @@ void HAL_I2C_Flush_Data(HAL_I2C_Interface i2c, void* reserved); bool HAL_I2C_Is_Enabled(HAL_I2C_Interface i2c, void* reserved); void HAL_I2C_Set_Callback_On_Receive(HAL_I2C_Interface i2c, void (*function)(int), void* reserved); void HAL_I2C_Set_Callback_On_Request(HAL_I2C_Interface i2c, void (*function)(void), void* reserved); +uint8_t HAL_I2C_Reset(HAL_I2C_Interface i2c, uint32_t reserved, void* reserve1); void HAL_I2C_Set_Speed_v1(uint32_t speed); diff --git a/hal/src/core/i2c_hal.c b/hal/src/core/i2c_hal.c index 5822d29ce9..ff8fe468d8 100644 --- a/hal/src/core/i2c_hal.c +++ b/hal/src/core/i2c_hal.c @@ -29,6 +29,7 @@ #include "timer_hal.h" #include "pinmap_impl.h" #include +#include "delay_hal.h" /* Private typedef -----------------------------------------------------------*/ @@ -80,6 +81,8 @@ typedef struct STM32_I2C_Info { void (*callback_onRequest)(void); void (*callback_onReceive)(int); + + I2C_Mode mode; } STM32_I2C_Info; /* @@ -161,6 +164,7 @@ void HAL_I2C_Begin(HAL_I2C_Interface i2c, I2C_Mode mode, uint8_t address, void* i2cMap[i2c]->txBufferIndex = 0; i2cMap[i2c]->txBufferLength = 0; + i2cMap[i2c]->mode = mode; /* Enable I2C clock */ *i2cMap[i2c]->I2C_RCC_APBRegister |= i2cMap[i2c]->I2C_RCC_APBClockEnable; @@ -520,6 +524,34 @@ void HAL_I2C_Set_Callback_On_Request(HAL_I2C_Interface i2c, void (*function)(voi i2cMap[i2c]->callback_onRequest = function; } +uint8_t HAL_I2C_Reset(HAL_I2C_Interface i2c, uint32_t reserved, void* reserved1) +{ + if (HAL_I2C_Is_Enabled(i2c, NULL)) { + HAL_I2C_End(i2c, NULL); + + HAL_Pin_Mode(i2cMap[i2c]->I2C_SDA_Pin, INPUT_PULLUP); //Turn SCA into high impedance input + HAL_Pin_Mode(i2cMap[i2c]->I2C_SCL_Pin, OUTPUT); //Turn SCL into a normal GPO + HAL_GPIO_Write(i2cMap[i2c]->I2C_SCL_Pin, 1); // Start idle HIGH + + //Generate 9 pulses on SCL to tell slave to release the bus + for(int i=0; i <9; i++) + { + HAL_GPIO_Write(i2cMap[i2c]->I2C_SCL_Pin, 0); + HAL_Delay_Microseconds(100); + HAL_GPIO_Write(i2cMap[i2c]->I2C_SCL_Pin, 1); + HAL_Delay_Microseconds(100); + } + + //Change SCL to be an input + HAL_Pin_Mode(i2cMap[i2c]->I2C_SCL_Pin, INPUT_PULLUP); + + HAL_I2C_Begin(i2c, i2cMap[i2c]->mode, i2cMap[i2c]->I2C_InitStructure.I2C_OwnAddress1 >> 1, NULL); + HAL_Delay_Milliseconds(50); + return 0; + } + return 1; +} + static void HAL_I2C_ER_InterruptHandler(HAL_I2C_Interface i2c) { #if 0 //Checks whether specified I2C interrupt has occurred and clear IT pending bit. diff --git a/hal/src/stm32f2xx/i2c_hal.c b/hal/src/stm32f2xx/i2c_hal.c index 8fa409d63d..ec24385ab9 100644 --- a/hal/src/stm32f2xx/i2c_hal.c +++ b/hal/src/stm32f2xx/i2c_hal.c @@ -31,6 +31,7 @@ #include #include "service_debug.h" #include "interrupts_hal.h" +#include "delay_hal.h" #ifdef LOG_SOURCE_CATEGORY LOG_SOURCE_CATEGORY("hal.i2c") @@ -240,6 +241,20 @@ void HAL_I2C_Begin(HAL_I2C_Interface i2c, I2C_Mode mode, uint8_t address, void* { STM32_Pin_Info* PIN_MAP = HAL_Pin_Map(); +#if PLATFORM_ID == 10 + /* + * On Electron both I2C_INTERFACE1 and I2C_INTERFACE2 use the same peripheral - I2C1, + * but on different pins. We cannot enable both of them at the same time. + */ + if (i2c == HAL_I2C_INTERFACE1 || i2c == HAL_I2C_INTERFACE2) { + HAL_I2C_Interface dependent = (i2c == HAL_I2C_INTERFACE1 ? HAL_I2C_INTERFACE2 : HAL_I2C_INTERFACE1); + if (HAL_I2C_Is_Enabled(dependent, NULL) == true) { + // Unfortunately we cannot return an error code here + return; + } + } +#endif + i2cMap[i2c]->rxBufferIndex = 0; i2cMap[i2c]->rxBufferLength = 0; @@ -764,6 +779,34 @@ void HAL_I2C_Set_Callback_On_Request(HAL_I2C_Interface i2c, void (*function)(voi i2cMap[i2c]->callback_onRequest = function; } +uint8_t HAL_I2C_Reset(HAL_I2C_Interface i2c, uint32_t reserved, void* reserved1) +{ + if (HAL_I2C_Is_Enabled(i2c, NULL)) { + HAL_I2C_End(i2c, NULL); + + HAL_Pin_Mode(i2cMap[i2c]->I2C_SDA_Pin, INPUT_PULLUP); //Turn SCA into high impedance input + HAL_Pin_Mode(i2cMap[i2c]->I2C_SCL_Pin, OUTPUT); //Turn SCL into a normal GPO + HAL_GPIO_Write(i2cMap[i2c]->I2C_SCL_Pin, 1); // Start idle HIGH + + //Generate 9 pulses on SCL to tell slave to release the bus + for(int i=0; i <9; i++) + { + HAL_GPIO_Write(i2cMap[i2c]->I2C_SCL_Pin, 0); + HAL_Delay_Microseconds(100); + HAL_GPIO_Write(i2cMap[i2c]->I2C_SCL_Pin, 1); + HAL_Delay_Microseconds(100); + } + + //Change SCL to be an input + HAL_Pin_Mode(i2cMap[i2c]->I2C_SCL_Pin, INPUT_PULLUP); + + HAL_I2C_Begin(i2c, i2cMap[i2c]->mode, i2cMap[i2c]->I2C_InitStructure.I2C_OwnAddress1 >> 1, NULL); + HAL_Delay_Milliseconds(50); + return 0; + } + return 1; +} + static void HAL_I2C_ER_InterruptHandler(HAL_I2C_Interface i2c) { /* Useful for debugging, diable to save time */ @@ -838,7 +881,18 @@ static void HAL_I2C_ER_InterruptHandler(HAL_I2C_Interface i2c) */ void I2C1_ER_irq(void) { +#if PLATFORM_ID == 10 // Electron + if (HAL_I2C_Is_Enabled(HAL_I2C_INTERFACE1, NULL)) + { + HAL_I2C_ER_InterruptHandler(HAL_I2C_INTERFACE1); + } + else if (HAL_I2C_Is_Enabled(HAL_I2C_INTERFACE2, NULL)) + { + HAL_I2C_ER_InterruptHandler(HAL_I2C_INTERFACE2); + } +#else HAL_I2C_ER_InterruptHandler(HAL_I2C_INTERFACE1); +#endif } #if PLATFORM_ID == 10 // Electron @@ -865,7 +919,7 @@ static void HAL_I2C_EV_InterruptHandler(HAL_I2C_Interface i2c) * The purpose is to make sure that both ADDR and STOPF flags are cleared if both are found set */ uint32_t sr1 = I2C_ReadRegister(i2cMap[i2c]->I2C_Peripheral, I2C_Register_SR1); - + /* EV4 */ if (sr1 & I2C_EVENT_SLAVE_STOP_DETECTED) { @@ -955,7 +1009,18 @@ static void HAL_I2C_EV_InterruptHandler(HAL_I2C_Interface i2c) */ void I2C1_EV_irq(void) { +#if PLATFORM_ID == 10 // Electron + if (HAL_I2C_Is_Enabled(HAL_I2C_INTERFACE1, NULL)) + { + HAL_I2C_EV_InterruptHandler(HAL_I2C_INTERFACE1); + } + else if (HAL_I2C_Is_Enabled(HAL_I2C_INTERFACE2, NULL)) + { + HAL_I2C_EV_InterruptHandler(HAL_I2C_INTERFACE2); + } +#else HAL_I2C_EV_InterruptHandler(HAL_I2C_INTERFACE1); +#endif } #if PLATFORM_ID == 10 // Electron diff --git a/hal/src/template/i2c_hal.cpp b/hal/src/template/i2c_hal.cpp index be7e949479..b88cb463fe 100644 --- a/hal/src/template/i2c_hal.cpp +++ b/hal/src/template/i2c_hal.cpp @@ -126,3 +126,8 @@ void HAL_I2C1_ER_Handler(void) void HAL_I2C_Enable_DMA_Mode(HAL_I2C_Interface i2c, bool enable,void* reserved) { } + +uint8_t HAL_I2C_Reset(HAL_I2C_Interface i2c, uint32_t reserved, void* reserved1) +{ + return 0; +} diff --git a/user/tests/wiring/i2c_master_slave/i2c_master/i2c_master.cpp b/user/tests/wiring/i2c_master_slave/i2c_master/i2c_master.cpp index 0ca4606cc8..6fd9143850 100644 --- a/user/tests/wiring/i2c_master_slave/i2c_master/i2c_master.cpp +++ b/user/tests/wiring/i2c_master_slave/i2c_master/i2c_master.cpp @@ -16,8 +16,8 @@ static int I2C_Test_Counter = 2; static void I2C_Master_Configure() { - Wire.setSpeed(400000); - Wire.begin(); + USE_WIRE.setSpeed(400000); + USE_WIRE.begin(); } test(I2C_Master_Slave_Master_Variable_Length_Transfer) @@ -43,11 +43,11 @@ test(I2C_Master_Slave_Master_Variable_Length_Transfer) memcpy(I2C_Master_Tx_Buffer, MASTER_TEST_MESSAGE, sizeof(MASTER_TEST_MESSAGE)); memcpy(I2C_Master_Tx_Buffer + sizeof(MASTER_TEST_MESSAGE), (void*)&requestedLength, sizeof(uint32_t)); - Wire.beginTransmission(I2C_ADDRESS); - Wire.write(I2C_Master_Tx_Buffer, TRANSFER_LENGTH_1); + USE_WIRE.beginTransmission(I2C_ADDRESS); + USE_WIRE.write(I2C_Master_Tx_Buffer, TRANSFER_LENGTH_1); // End with STOP - Wire.endTransmission(true); + USE_WIRE.endTransmission(true); // delay(I2C_DELAY); if (requestedLength == 0) @@ -55,12 +55,12 @@ test(I2C_Master_Slave_Master_Variable_Length_Transfer) // Now read out requestedLength bytes memset(I2C_Master_Rx_Buffer, 0, sizeof(I2C_Master_Rx_Buffer)); - Wire.requestFrom(I2C_ADDRESS, requestedLength); - assertEqual(requestedLength, Wire.available()); + USE_WIRE.requestFrom(I2C_ADDRESS, requestedLength); + assertEqual(requestedLength, USE_WIRE.available()); uint32_t count = 0; - while(Wire.available()) { - I2C_Master_Rx_Buffer[count++] = Wire.read(); + while(USE_WIRE.available()) { + I2C_Master_Rx_Buffer[count++] = USE_WIRE.read(); } // Serial.print("< "); // Serial.println((const char *)I2C_Master_Rx_Buffer); @@ -69,7 +69,7 @@ test(I2C_Master_Slave_Master_Variable_Length_Transfer) requestedLength--; } - Wire.end(); + USE_WIRE.end(); } test(I2C_Master_Slave_Master_Variable_Length_Transfer_Slave_Tx_Buffer_Underflow) @@ -100,11 +100,11 @@ test(I2C_Master_Slave_Master_Variable_Length_Transfer_Slave_Tx_Buffer_Underflow) memcpy(I2C_Master_Tx_Buffer, MASTER_TEST_MESSAGE, sizeof(MASTER_TEST_MESSAGE)); memcpy(I2C_Master_Tx_Buffer + sizeof(MASTER_TEST_MESSAGE), (void*)&requestedLength, sizeof(uint32_t)); - Wire.beginTransmission(I2C_ADDRESS); - Wire.write(I2C_Master_Tx_Buffer, TRANSFER_LENGTH_1); + USE_WIRE.beginTransmission(I2C_ADDRESS); + USE_WIRE.write(I2C_Master_Tx_Buffer, TRANSFER_LENGTH_1); // End with STOP - Wire.endTransmission(true); + USE_WIRE.endTransmission(true); // delay(I2C_DELAY); if (requestedLength == 0) @@ -112,13 +112,13 @@ test(I2C_Master_Slave_Master_Variable_Length_Transfer_Slave_Tx_Buffer_Underflow) // Now read out requestedLength bytes memset(I2C_Master_Rx_Buffer, 0, sizeof(I2C_Master_Rx_Buffer)); - Wire.requestFrom(I2C_ADDRESS, requestedLength + (requestedLength & 0x01)); - if (Wire.available() != 0) { - assertEqual(requestedLength + (requestedLength & 0x01), Wire.available()); + USE_WIRE.requestFrom(I2C_ADDRESS, requestedLength + (requestedLength & 0x01)); + if (USE_WIRE.available() != 0) { + assertEqual(requestedLength + (requestedLength & 0x01), USE_WIRE.available()); uint32_t count = 0; - while(Wire.available()) { - I2C_Master_Rx_Buffer[count++] = Wire.read(); + while(USE_WIRE.available()) { + I2C_Master_Rx_Buffer[count++] = USE_WIRE.read(); } // Serial.print("< "); // Serial.println((const char *)I2C_Master_Rx_Buffer); @@ -133,5 +133,5 @@ test(I2C_Master_Slave_Master_Variable_Length_Transfer_Slave_Tx_Buffer_Underflow) requestedLength--; } - Wire.end(); + USE_WIRE.end(); } diff --git a/user/tests/wiring/i2c_master_slave/i2c_master/test.mk b/user/tests/wiring/i2c_master_slave/i2c_master/test.mk new file mode 100644 index 0000000000..357e1b9819 --- /dev/null +++ b/user/tests/wiring/i2c_master_slave/i2c_master/test.mk @@ -0,0 +1,23 @@ +INCLUDE_DIRS += $(SOURCE_PATH)/$(USRSRC) # add user sources to include path +# add C and CPP files - if USRSRC is not empty, then add a slash +CPPSRC += $(call target_files,$(USRSRC_SLASH),*.cpp) +CSRC += $(call target_files,$(USRSRC_SLASH),*.c) + +APPSOURCES=$(call target_files,$(USRSRC_SLASH),*.cpp) +APPSOURCES+=$(call target_files,$(USRSRC_SLASH),*.c) +ifeq ($(strip $(APPSOURCES)),) +$(error "No sources found in $(SOURCE_PATH)/$(USRSRC)") +endif + +ifeq ("${USE_WIRE}",) +USE_WIRE=Wire +else ifeq ("${USE_WIRE}","Wire1") +USE_WIRE=Wire1 +else ifeq ("${USE_WIRE}","Wire3") +USE_WIRE=Wire3 +else +USE_WIRE=Wire +endif + +CFLAGS += -DUSE_WIRE=${USE_WIRE} +CXXFLAGS += -DUSE_WIRE=${USE_WIRE} diff --git a/user/tests/wiring/i2c_master_slave/i2c_slave/i2c_slave.cpp b/user/tests/wiring/i2c_master_slave/i2c_slave/i2c_slave.cpp index f2822eb4c6..61cfbcb1fd 100644 --- a/user/tests/wiring/i2c_master_slave/i2c_slave/i2c_slave.cpp +++ b/user/tests/wiring/i2c_master_slave/i2c_slave/i2c_slave.cpp @@ -26,14 +26,14 @@ void I2C_Slave_On_Request_Callback(void) { delayMicroseconds(random_range(0, 50000)); memset(I2C_Slave_Tx_Buffer, 0, sizeof(I2C_Slave_Tx_Buffer)); memcpy(I2C_Slave_Tx_Buffer, SLAVE_TEST_MESSAGE_2, requestedLength); - Wire.write((const uint8_t*)I2C_Slave_Tx_Buffer, requestedLength); + USE_WIRE.write((const uint8_t*)I2C_Slave_Tx_Buffer, requestedLength); } void I2C_Slave_On_Receive_Callback(int) { - assertEqual(Wire.available(), TRANSFER_LENGTH_1); + assertEqual(USE_WIRE.available(), TRANSFER_LENGTH_1); int count = 0; - while(Wire.available()) { - I2C_Slave_Rx_Buffer[count++] = Wire.read(); + while(USE_WIRE.available()) { + I2C_Slave_Rx_Buffer[count++] = USE_WIRE.read(); } I2C_Slave_Rx_Buffer[count] = 0x00; @@ -53,14 +53,14 @@ test(I2C_Master_Slave_Slave_Transfer) { Serial.println("This is Slave"); Serial.blockOnOverrun(false); - Wire.begin(I2C_ADDRESS); - Wire.stretchClock(true); - Wire.onRequest(I2C_Slave_On_Request_Callback); - Wire.onReceive(I2C_Slave_On_Receive_Callback); + USE_WIRE.begin(I2C_ADDRESS); + USE_WIRE.stretchClock(true); + USE_WIRE.onRequest(I2C_Slave_On_Request_Callback); + USE_WIRE.onReceive(I2C_Slave_On_Receive_Callback); while(done == 0) { delay(100); } - Wire.end(); + USE_WIRE.end(); } diff --git a/user/tests/wiring/i2c_master_slave/i2c_slave/test.mk b/user/tests/wiring/i2c_master_slave/i2c_slave/test.mk new file mode 100644 index 0000000000..357e1b9819 --- /dev/null +++ b/user/tests/wiring/i2c_master_slave/i2c_slave/test.mk @@ -0,0 +1,23 @@ +INCLUDE_DIRS += $(SOURCE_PATH)/$(USRSRC) # add user sources to include path +# add C and CPP files - if USRSRC is not empty, then add a slash +CPPSRC += $(call target_files,$(USRSRC_SLASH),*.cpp) +CSRC += $(call target_files,$(USRSRC_SLASH),*.c) + +APPSOURCES=$(call target_files,$(USRSRC_SLASH),*.cpp) +APPSOURCES+=$(call target_files,$(USRSRC_SLASH),*.c) +ifeq ($(strip $(APPSOURCES)),) +$(error "No sources found in $(SOURCE_PATH)/$(USRSRC)") +endif + +ifeq ("${USE_WIRE}",) +USE_WIRE=Wire +else ifeq ("${USE_WIRE}","Wire1") +USE_WIRE=Wire1 +else ifeq ("${USE_WIRE}","Wire3") +USE_WIRE=Wire3 +else +USE_WIRE=Wire +endif + +CFLAGS += -DUSE_WIRE=${USE_WIRE} +CXXFLAGS += -DUSE_WIRE=${USE_WIRE} diff --git a/user/tests/wiring/i2c_master_slave/application.cpp b/user/tests/wiring/i2c_master_slave_old/application.cpp similarity index 100% rename from user/tests/wiring/i2c_master_slave/application.cpp rename to user/tests/wiring/i2c_master_slave_old/application.cpp diff --git a/user/tests/wiring/i2c_master_slave/i2c_master_slave.cpp b/user/tests/wiring/i2c_master_slave_old/i2c_master_slave.cpp similarity index 100% rename from user/tests/wiring/i2c_master_slave/i2c_master_slave.cpp rename to user/tests/wiring/i2c_master_slave_old/i2c_master_slave.cpp diff --git a/user/tests/wiring/i2c_mcp23017/i2c.cpp b/user/tests/wiring/i2c_mcp23017/i2c.cpp index b0859de4c1..5101f424b9 100644 --- a/user/tests/wiring/i2c_mcp23017/i2c.cpp +++ b/user/tests/wiring/i2c_mcp23017/i2c.cpp @@ -1,4 +1,3 @@ -#include #include "application.h" #include "unit-test/unit-test.h" #include "i2c_helper.h" @@ -10,12 +9,12 @@ test(0_I2C_scanBus) { // Scan I2C bus for (uint8_t addr = 0x01; addr < 0x7f; addr++) { ts1 = millis(); - Wire.beginTransmission(addr); - int32_t err = Wire.endTransmission(); + USE_WIRE.beginTransmission(addr); + int32_t err = USE_WIRE.endTransmission(); ts2 = millis(); if (err == 0) { - i2c::devices.push_back(addr); + i2c::devices.append(addr); DEBUG("I2C device @ 0x%02x", addr); } else if (err == 0x03) { // No one ACKed the address diff --git a/user/tests/wiring/i2c_mcp23017/i2c_helper.cpp b/user/tests/wiring/i2c_mcp23017/i2c_helper.cpp index 35c7f407e7..b59105258d 100644 --- a/user/tests/wiring/i2c_mcp23017/i2c_helper.cpp +++ b/user/tests/wiring/i2c_mcp23017/i2c_helper.cpp @@ -4,22 +4,22 @@ namespace i2c { uint32_t errorCount = 0; -std::vector devices; +spark::Vector devices; void reset() { - Wire.setSpeed(400000); - Wire.begin(); + USE_WIRE.setSpeed(400000); + USE_WIRE.begin(); // Just in case reset the bus - Wire.reset(); + USE_WIRE.reset(); errorCount = 0; } int32_t writeRegister(uint8_t slaveAddress, uint8_t addr, uint8_t val, bool stop) { - Wire.beginTransmission(slaveAddress); - Wire.write(addr); - Wire.write(val); - int32_t err = -Wire.endTransmission(stop); + USE_WIRE.beginTransmission(slaveAddress); + USE_WIRE.write(addr); + USE_WIRE.write(val); + int32_t err = -USE_WIRE.endTransmission(stop); if (err < 0) { ++errorCount; ERROR("%d e %d 0x%02x 0x%02x 1 %d", errorCount, err, slaveAddress, addr, stop); @@ -28,10 +28,10 @@ int32_t writeRegister(uint8_t slaveAddress, uint8_t addr, uint8_t val, bool stop } int32_t writeRegister(uint8_t slaveAddress, uint8_t addr, uint8_t* buffer, uint8_t len, bool stop) { - Wire.beginTransmission(slaveAddress); - Wire.write(addr); - Wire.write(buffer, len); - int32_t err = -Wire.endTransmission(stop); + USE_WIRE.beginTransmission(slaveAddress); + USE_WIRE.write(addr); + USE_WIRE.write(buffer, len); + int32_t err = -USE_WIRE.endTransmission(stop); if (err < 0) { ++errorCount; ERROR("%d e %d 0x%02x 0x%02x %d %d", errorCount, err, slaveAddress, addr, len, stop); @@ -40,13 +40,13 @@ int32_t writeRegister(uint8_t slaveAddress, uint8_t addr, uint8_t* buffer, uint8 } int32_t readRegister(uint8_t slaveAddress, uint8_t addr, bool stop, bool stopAfterWrite) { - Wire.beginTransmission(slaveAddress); - Wire.write(addr); - int32_t err = -Wire.endTransmission(stopAfterWrite); + USE_WIRE.beginTransmission(slaveAddress); + USE_WIRE.write(addr); + int32_t err = -USE_WIRE.endTransmission(stopAfterWrite); if (err == 0) { - err = Wire.requestFrom(slaveAddress, (uint8_t)1, (uint8_t)stop); + err = USE_WIRE.requestFrom(slaveAddress, (uint8_t)1, (uint8_t)stop); if (err == 1) { - return Wire.read(); + return USE_WIRE.read(); } else { ++errorCount; ERROR("%d r %d 0x%02x 0x%02x %d", errorCount, err, slaveAddress, addr, stop); @@ -59,14 +59,14 @@ int32_t readRegister(uint8_t slaveAddress, uint8_t addr, bool stop, bool stopAft } int32_t readRegister(uint8_t slaveAddress, uint8_t addr, uint8_t* buffer, uint8_t len, bool stop, bool stopAfterWrite) { - Wire.beginTransmission(slaveAddress); - Wire.write(addr); - int32_t err = -Wire.endTransmission(stopAfterWrite); + USE_WIRE.beginTransmission(slaveAddress); + USE_WIRE.write(addr); + int32_t err = -USE_WIRE.endTransmission(stopAfterWrite); if (err == 0) { - err = Wire.requestFrom(slaveAddress, len, (uint8_t)stop); + err = USE_WIRE.requestFrom(slaveAddress, len, (uint8_t)stop); if (err == len) { while (len-- > 0) { - uint8_t b = Wire.read(); + uint8_t b = USE_WIRE.read(); if (buffer != nullptr) (*buffer++) = b; } @@ -82,10 +82,10 @@ int32_t readRegister(uint8_t slaveAddress, uint8_t addr, uint8_t* buffer, uint8_ } int32_t readAddr(uint8_t slaveAddress, uint8_t* buffer, uint8_t len, bool stop) { - int32_t err = Wire.requestFrom(slaveAddress, len, (uint8_t)stop); + int32_t err = USE_WIRE.requestFrom(slaveAddress, len, (uint8_t)stop); if (err == len) { while(len-- > 0) { - (*buffer++) = Wire.read(); + (*buffer++) = USE_WIRE.read(); } } else { ++errorCount; diff --git a/user/tests/wiring/i2c_mcp23017/i2c_helper.h b/user/tests/wiring/i2c_mcp23017/i2c_helper.h index b4baada8aa..81e30e6f93 100644 --- a/user/tests/wiring/i2c_mcp23017/i2c_helper.h +++ b/user/tests/wiring/i2c_mcp23017/i2c_helper.h @@ -1,9 +1,6 @@ #ifndef I2C_REG_H_ #define I2C_REG_H_ -#include -#include - // Some helper functions namespace i2c { @@ -19,7 +16,7 @@ int32_t readRegister(uint8_t slaveAddress, uint8_t addr, uint8_t* buffer, uint8_ int32_t readAddr(uint8_t slaveAddress, uint8_t* buffer, uint8_t len, bool stop); extern uint32_t errorCount; -extern std::vector devices; +extern spark::Vector devices; } // namespace i2c #endif // I2C_REG_H_ diff --git a/user/tests/wiring/i2c_mcp23017/mcp23017.cpp b/user/tests/wiring/i2c_mcp23017/mcp23017.cpp index 1a68489dfb..812d92ea9f 100644 --- a/user/tests/wiring/i2c_mcp23017/mcp23017.cpp +++ b/user/tests/wiring/i2c_mcp23017/mcp23017.cpp @@ -1,8 +1,8 @@ -#include #include "application.h" #include "unit-test/unit-test.h" #include "i2c_helper.h" #include "interferer.h" +#include #define MCP23017_BASE_ADDRESS 0x20 @@ -50,7 +50,7 @@ test(1_I2C_MCP23017_doRequestControlNoStopReadNoStop) { // Perform single 4-byte read and end it with STOP i2c::readRegister(s_mcpAddress, 0x00, nullptr, 4, true, false); - Wire.end(); + USE_WIRE.end(); assertEqual(i2c::errorCount, 0); } @@ -79,7 +79,7 @@ test(2_I2C_MCP23017_doRequestControlStopReadStop) { // and STOP after read i2c::readRegister(s_mcpAddress, 0x00, nullptr, 4, true, true); - Wire.end(); + USE_WIRE.end(); assertEqual(i2c::errorCount, 0); } @@ -109,7 +109,7 @@ test(3_I2C_MCP23017_doRequestControlNoStopReadStop) { // and STOP after read i2c::readRegister(s_mcpAddress, 0x00, nullptr, 4, true, false); - Wire.end(); + USE_WIRE.end(); assertEqual(i2c::errorCount, 0); } @@ -140,7 +140,7 @@ test(4_I2C_MCP23017_doRequestControlStopReadNoStop) { // and STOP after read i2c::readRegister(s_mcpAddress, 0x00, nullptr, 4, true, true); - Wire.end(); + USE_WIRE.end(); assertEqual(i2c::errorCount, 0); } diff --git a/user/tests/wiring/i2c_mcp23017/test.mk b/user/tests/wiring/i2c_mcp23017/test.mk new file mode 100644 index 0000000000..357e1b9819 --- /dev/null +++ b/user/tests/wiring/i2c_mcp23017/test.mk @@ -0,0 +1,23 @@ +INCLUDE_DIRS += $(SOURCE_PATH)/$(USRSRC) # add user sources to include path +# add C and CPP files - if USRSRC is not empty, then add a slash +CPPSRC += $(call target_files,$(USRSRC_SLASH),*.cpp) +CSRC += $(call target_files,$(USRSRC_SLASH),*.c) + +APPSOURCES=$(call target_files,$(USRSRC_SLASH),*.cpp) +APPSOURCES+=$(call target_files,$(USRSRC_SLASH),*.c) +ifeq ($(strip $(APPSOURCES)),) +$(error "No sources found in $(SOURCE_PATH)/$(USRSRC)") +endif + +ifeq ("${USE_WIRE}",) +USE_WIRE=Wire +else ifeq ("${USE_WIRE}","Wire1") +USE_WIRE=Wire1 +else ifeq ("${USE_WIRE}","Wire3") +USE_WIRE=Wire3 +else +USE_WIRE=Wire +endif + +CFLAGS += -DUSE_WIRE=${USE_WIRE} +CXXFLAGS += -DUSE_WIRE=${USE_WIRE} diff --git a/user/tests/wiring/no_fixture/build.mk b/user/tests/wiring/no_fixture/test.mk similarity index 100% rename from user/tests/wiring/no_fixture/build.mk rename to user/tests/wiring/no_fixture/test.mk diff --git a/user/tests/wiring/no_fixture/wire.cpp b/user/tests/wiring/no_fixture/wire.cpp index c61b780a10..b076988293 100644 --- a/user/tests/wiring/no_fixture/wire.cpp +++ b/user/tests/wiring/no_fixture/wire.cpp @@ -35,4 +35,27 @@ test(WIRE_01_Wire_end_begin_end) assertTrue(pinAvailable(D1)); } +#if PLATFORM_ID == 10 +test(WIRE_02_Wire_and_Wire1_cannot_be_enabled_simultaneously_on_Electron) +{ + // Just in case disable both of them beforehand to enter a know state + Wire.end(); + Wire1.end(); + Wire.begin(); + assertTrue(Wire.isEnabled()); + Wire1.begin(); + assertFalse(Wire1.isEnabled()); + + Wire.end(); + assertFalse(Wire.isEnabled()); + + Wire1.begin(); + assertTrue(Wire1.isEnabled()); + Wire.begin(); + assertFalse(Wire.isEnabled()); + + Wire1.end(); + assertFalse(Wire1.isEnabled()); +} +#endif // PLATFORM_ID == 10 diff --git a/user/tests/wiring/no_fixture_long_running/build.mk b/user/tests/wiring/no_fixture_long_running/test.mk similarity index 100% rename from user/tests/wiring/no_fixture_long_running/build.mk rename to user/tests/wiring/no_fixture_long_running/test.mk diff --git a/user/tests/wiring/spi_master_slave/spi_master/build.mk b/user/tests/wiring/spi_master_slave/spi_master/test.mk similarity index 100% rename from user/tests/wiring/spi_master_slave/spi_master/build.mk rename to user/tests/wiring/spi_master_slave/spi_master/test.mk diff --git a/user/tests/wiring/spi_master_slave/spi_slave/build.mk b/user/tests/wiring/spi_master_slave/spi_slave/test.mk similarity index 100% rename from user/tests/wiring/spi_master_slave/spi_slave/build.mk rename to user/tests/wiring/spi_master_slave/spi_slave/test.mk diff --git a/wiring/src/spark_wiring_i2c.cpp b/wiring/src/spark_wiring_i2c.cpp index 918fc99d17..06276b35f1 100644 --- a/wiring/src/spark_wiring_i2c.cpp +++ b/wiring/src/spark_wiring_i2c.cpp @@ -201,43 +201,7 @@ bool TwoWire::isEnabled() return HAL_I2C_Is_Enabled(_i2c, NULL); } -#include "gpio_hal.h" -#include "spark_wiring_constants.h" -#include "spark_wiring_ticks.h" void TwoWire::reset() { - pin_t _SCA; - pin_t _SCL; - - if (_i2c==HAL_I2C_INTERFACE1) - { - _SCA = D0; - _SCL = D1; - } - else - { - return; // todo fill in other pins. The pins should ideally come from the HAL. - } - - this->end(); - - HAL_Pin_Mode(_SCA, INPUT_PULLUP); //Turn SCA into high impedance input - HAL_Pin_Mode(_SCL, OUTPUT); //Turn SCL into a normal GPO - HAL_GPIO_Write(_SCL, HIGH); // Start idle HIGH - - //Generate 9 pulses on SCL to tell slave to release the bus - for(int i=0; i <9; i++) - { - HAL_GPIO_Write(_SCL, LOW); - delayMicroseconds(100); - HAL_GPIO_Write(_SCL, HIGH); - delayMicroseconds(100); - } - - //Change SCL to be an input - HAL_Pin_Mode(_SCL, INPUT_PULLUP); - - //Start i2c over again - begin(); - delay(50); + HAL_I2C_Reset(_i2c, 0, NULL); }