Skip to content

Commit 6ae571d

Browse files
author
Jamie Smith
authored
LPC1768: Fix I2C pins not being open drain, fix destroying and recreating I2C making transactions fail (#275)
* LPC1768: Fix I2C pins not being open drain, fix destroying and recreating I2C making transactions fail * bus -> peripheral
1 parent a40e819 commit 6ae571d

File tree

1 file changed

+33
-0
lines changed

1 file changed

+33
-0
lines changed

targets/TARGET_NXP/TARGET_LPC176X/i2c_api.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,14 @@
2222
#include "cmsis.h"
2323
#include "pinmap.h"
2424

25+
// Change to 1 to enable debug prints.
26+
#define LPC1768_I2C_DEBUG 0
27+
28+
#if LPC1768_I2C_DEBUG
29+
#include <stdio.h>
30+
#include <inttypes.h>
31+
#endif
32+
2533
static const PinMap PinMap_I2C_SDA[] = {
2634
{P0_0 , I2C_1, 3},
2735
{P0_10, I2C_2, 2},
@@ -83,6 +91,10 @@ static int i2c_wait_SI(i2c_t *obj) {
8391
return 0;
8492
}
8593

94+
static inline void i2c_interface_disable(i2c_t *obj) {
95+
I2C_CONCLR(obj) = 0x40;
96+
}
97+
8698
static inline void i2c_interface_enable(i2c_t *obj) {
8799
I2C_CONSET(obj) = 0x40;
88100
}
@@ -107,17 +119,30 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
107119

108120
// set default frequency at 100k
109121
i2c_frequency(obj, 100000);
122+
123+
// Reset the I2C peripheral by clearing all flags, including I2EN.
124+
// This does a software reset of sorts, which is important because the I2C::recover()
125+
// function, which is called before initializing the bus, seems to put the I2C
126+
// peripheral in a weird state where the next transaction will fail.
127+
i2c_interface_disable(obj);
110128
i2c_conclr(obj, 1, 1, 1, 1);
129+
111130
i2c_interface_enable(obj);
112131

113132
pinmap_pinout(sda, PinMap_I2C_SDA);
133+
pin_mode(sda, OpenDrain);
114134
pinmap_pinout(scl, PinMap_I2C_SCL);
135+
pin_mode(scl, OpenDrain);
115136
}
116137

117138
inline int i2c_start(i2c_t *obj) {
118139
int status = 0;
119140
int isInterrupted = I2C_CONSET(obj) & (1 << 3);
120141

142+
#if LPC1768_I2C_DEBUG
143+
printf("i2c_start(): status was originally 0x%x\n", i2c_status(obj));
144+
#endif
145+
121146
// 8.1 Before master mode can be entered, I2CON must be initialised to:
122147
// - I2EN STA STO SI AA - -
123148
// - 1 0 0 x x - -
@@ -135,6 +160,10 @@ inline int i2c_start(i2c_t *obj) {
135160
i2c_wait_SI(obj);
136161
status = i2c_status(obj);
137162

163+
#if LPC1768_I2C_DEBUG
164+
printf("i2c_start(): status is now 0x%x\n", status);
165+
#endif
166+
138167
// Clear start bit now that it's transmitted
139168
i2c_conclr(obj, 1, 0, 0, 0);
140169
return status;
@@ -303,6 +332,10 @@ int i2c_byte_read(i2c_t *obj, int last) {
303332
int i2c_byte_write(i2c_t *obj, int data) {
304333
int ack;
305334
int status = i2c_do_write(obj, (data & 0xFF), 0);
335+
336+
#if LPC1768_I2C_DEBUG
337+
printf("i2c_do_write(0x%hhx) returned 0x%x\n", data & 0xFF, status);
338+
#endif
306339

307340
switch(status) {
308341
case 0x18: case 0x28: // Master transmit ACKs

0 commit comments

Comments
 (0)