diff options
author | Ben Fennema <fennema@google.com> | 2017-12-21 21:33:43 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2017-12-21 21:33:43 +0000 |
commit | d6104b39af592750d6fb8554765663c83e2fe00c (patch) | |
tree | 435b840fcf7750eb189af390cbc7812ea56eee17 | |
parent | d70ba6fe311d24462ce0e8203cf53b32af7be6b9 (diff) | |
parent | aad7f8db6874a2527c05e1b5431952e953c8e4c0 (diff) | |
download | contexthub-d6104b39af592750d6fb8554765663c83e2fe00c.tar.gz |
nanohub: i2c: detect and clock through stuck low sda am: 44b122a273
am: aad7f8db68
Change-Id: If81bc9be8fb01dc47e193878e60d49e119beef95
-rw-r--r-- | firmware/os/core/timer.c | 8 | ||||
-rw-r--r-- | firmware/os/inc/timer.h | 1 | ||||
-rw-r--r-- | firmware/os/platform/stm32/i2c.c | 46 |
3 files changed, 55 insertions, 0 deletions
diff --git a/firmware/os/core/timer.c b/firmware/os/core/timer.c index ace80723..f9c33523 100644 --- a/firmware/os/core/timer.c +++ b/firmware/os/core/timer.c @@ -62,6 +62,14 @@ uint64_t timGetTime(void) return platGetTicks(); } +void timDelay(uint32_t length) +{ + uint64_t curTime = timGetTime(); + + while (curTime + length > timGetTime()) + ; +} + static struct Timer *timFindTimerById(uint32_t timId) /* no locks taken. be careful what you do with this */ { uint32_t i; diff --git a/firmware/os/inc/timer.h b/firmware/os/inc/timer.h index abc5e19f..30e359a2 100644 --- a/firmware/os/inc/timer.h +++ b/firmware/os/inc/timer.h @@ -38,6 +38,7 @@ typedef void (*TimTimerCbkF)(uint32_t timerId, void* data); uint64_t timGetTime(void); /* Time since some stable reference point in nanoseconds */ +void timDelay(uint32_t length); uint32_t timTimerSet(uint64_t length, uint32_t jitterPpm, uint32_t driftPpm, TimTimerCbkF cbk, void* data, bool oneShot); /* return timer id or 0 if failed */ uint32_t timTimerSetAsApp(uint64_t length, uint32_t jitterPpm, uint32_t driftPpm, uint32_t tid, void* data, bool oneShot); /* return timer id or 0 if failed */ diff --git a/firmware/os/platform/stm32/i2c.c b/firmware/os/platform/stm32/i2c.c index 189e8f9d..7ba7b7ce 100644 --- a/firmware/os/platform/stm32/i2c.c +++ b/firmware/os/platform/stm32/i2c.c @@ -26,6 +26,7 @@ #include <atomicBitset.h> #include <atomic.h> #include <platform.h> +#include <timer.h> #include <plat/cmsis.h> #include <plat/dma.h> @@ -775,6 +776,49 @@ static inline struct Gpio* stmI2cGpioInit(const struct StmI2cBoardCfg *board, co return gpio; } +static int i2cMasterReset(uint32_t busId, uint32_t speed) +{ + struct Gpio *sda, *scl; + int cnt = 0; + uint32_t delay; + + if (busId >= ARRAY_SIZE(mStmI2cDevs)) + return -EINVAL; + + const struct StmI2cBoardCfg *board = boardStmI2cCfg(busId); + if (!board) + return -EINVAL; + + sda = gpioRequest(board->gpioSda.gpioNum); + gpioConfigOutput(sda, board->gpioSpeed, GPIO_PULL_NONE, GPIO_OUT_OPEN_DRAIN, 1); + if (gpioGet(sda) == 0) { + // 50% duty cycle for the clock + delay = 500000000UL/speed; + + scl = gpioRequest(board->gpioScl.gpioNum); + gpioConfigOutput(scl, board->gpioSpeed, GPIO_PULL_NONE, GPIO_OUT_OPEN_DRAIN, 1); + do { + // generate clock pulse + gpioSet(scl, 1); + timDelay(delay); + gpioSet(scl, 0); + timDelay(delay); + cnt ++; + } while (gpioGet(sda) == 0 && cnt < 9); + + // generate STOP condition + gpioSet(sda, 0); + gpioSet(scl, 1); + timDelay(delay); + gpioSet(sda, 1); + timDelay(delay); + gpioRelease(scl); + } + gpioRelease(sda); + + return cnt; +} + int i2cMasterRequest(uint32_t busId, uint32_t speed) { if (busId >= ARRAY_SIZE(mStmI2cDevs)) @@ -797,6 +841,8 @@ int i2cMasterRequest(uint32_t busId, uint32_t speed) pdev->last = 1; atomicBitsetInit(mXfersValid, I2C_MAX_QUEUE_DEPTH); + i2cMasterReset(busId, speed); + pdev->scl = stmI2cGpioInit(board, &board->gpioScl); pdev->sda = stmI2cGpioInit(board, &board->gpioSda); |