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

[Electron] Wire1 fixes #1302

Merged
merged 7 commits into from
May 9, 2017
1 change: 1 addition & 0 deletions hal/inc/hal_dynalib_i2c.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
1 change: 1 addition & 0 deletions hal/inc/i2c_hal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
32 changes: 32 additions & 0 deletions hal/src/core/i2c_hal.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "timer_hal.h"
#include "pinmap_impl.h"
#include <stddef.h>
#include "delay_hal.h"

/* Private typedef -----------------------------------------------------------*/

Expand Down Expand Up @@ -80,6 +81,8 @@ typedef struct STM32_I2C_Info {

void (*callback_onRequest)(void);
void (*callback_onReceive)(int);

I2C_Mode mode;
} STM32_I2C_Info;

/*
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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.
Expand Down
67 changes: 66 additions & 1 deletion hal/src/stm32f2xx/i2c_hal.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include <stddef.h>
#include "service_debug.h"
#include "interrupts_hal.h"
#include "delay_hal.h"

#ifdef LOG_SOURCE_CATEGORY
LOG_SOURCE_CATEGORY("hal.i2c")
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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
Expand All @@ -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)
{
Expand Down Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions hal/src/template/i2c_hal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
38 changes: 19 additions & 19 deletions user/tests/wiring/i2c_master_slave/i2c_master/i2c_master.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -43,24 +43,24 @@ 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)
break;

// 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);
Expand All @@ -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)
Expand Down Expand Up @@ -100,25 +100,25 @@ 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)
break;

// 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);
Expand All @@ -133,5 +133,5 @@ test(I2C_Master_Slave_Master_Variable_Length_Transfer_Slave_Tx_Buffer_Underflow)
requestedLength--;
}

Wire.end();
USE_WIRE.end();
}
23 changes: 23 additions & 0 deletions user/tests/wiring/i2c_master_slave/i2c_master/test.mk
Original file line number Diff line number Diff line change
@@ -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}
18 changes: 9 additions & 9 deletions user/tests/wiring/i2c_master_slave/i2c_slave/i2c_slave.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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();
}
23 changes: 23 additions & 0 deletions user/tests/wiring/i2c_master_slave/i2c_slave/test.mk
Original file line number Diff line number Diff line change
@@ -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}
7 changes: 3 additions & 4 deletions user/tests/wiring/i2c_mcp23017/i2c.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#include <algorithm>
#include "application.h"
#include "unit-test/unit-test.h"
#include "i2c_helper.h"
Expand All @@ -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
Expand Down
Loading