Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit e399a64

Browse files
committedAug 12, 2022
[rtl872x] hal: GPIO and I2C fixes.
1 parent efcf215 commit e399a64

File tree

3 files changed

+68
-46
lines changed

3 files changed

+68
-46
lines changed
 

‎hal/src/rtl872x/gpio_hal.cpp

+28-11
Original file line numberDiff line numberDiff line change
@@ -141,18 +141,19 @@ int hal_gpio_configure(hal_pin_t pin, const hal_gpio_config_t* conf, void* reser
141141
GPIO_InitStruct.GPIO_Pin = rtlPin;
142142

143143
switch (mode) {
144-
case OUTPUT:
145-
case OUTPUT_OPEN_DRAIN: {
144+
case OUTPUT: {
146145
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
147146
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
148147
break;
149148
}
150-
case INPUT: {
149+
case INPUT:
150+
case OUTPUT_OPEN_DRAIN: {
151151
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
152152
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
153153
break;
154154
}
155-
case INPUT_PULLUP: {
155+
case INPUT_PULLUP:
156+
case OUTPUT_OPEN_DRAIN_PULLUP: {
156157
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
157158
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
158159
break;
@@ -162,11 +163,6 @@ int hal_gpio_configure(hal_pin_t pin, const hal_gpio_config_t* conf, void* reser
162163
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN;
163164
break;
164165
}
165-
case OUTPUT_OPEN_DRAIN_PULLUP: {
166-
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
167-
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
168-
break;
169-
}
170166
case PIN_MODE_SWD: {
171167
if (isSwdPin(pinInfo)) {
172168
//"Pinmux_Swdon"
@@ -233,12 +229,33 @@ void hal_gpio_write(hal_pin_t pin, uint8_t value) {
233229
#if HAL_PLATFORM_IO_EXTENSION && MODULE_FUNCTION != MOD_FUNC_BOOTLOADER
234230
if (pinInfo->type == HAL_PIN_TYPE_MCU) {
235231
#endif
236-
uint32_t rtlPin = hal_pin_to_rtl_pin(pin);
237232
// TODO: PWM have conflict with GPIO OUTPUT mode on Realtek
238233
if (pinInfo->pin_func == PF_PWM) {
239234
hal_gpio_mode(pin, OUTPUT);
240235
}
241-
GPIO_WriteBit(rtlPin, value);
236+
237+
auto mode = hal_gpio_get_mode(pin);
238+
hal_pin_info_t* pin_info = hal_pin_map() + pin;
239+
GPIO_TypeDef * gpiobase = ((pin_info->gpio_port == RTL_PORT_A) ? GPIOA_BASE : GPIOB_BASE);
240+
// Dirty hack: As per the description of EXT_PORT register in the user manual,
241+
// "When Port A is configured as Input, then reading this location reads
242+
// the values on the signal. When the data direction of Port A is set as
243+
// Output, reading this location reads the data register for Port A."
244+
if (value) {
245+
if (mode == OUTPUT_OPEN_DRAIN || mode == OUTPUT_OPEN_DRAIN_PULLUP) {
246+
// Output 1, it should read back 1 if idle or 0 if it is pulled down by external signal
247+
// Configure it as input meets the requirements.
248+
gpiobase->PORT[0].DDR &= (~(1 << pin_info->gpio_pin));
249+
} else {
250+
gpiobase->PORT[0].DR |= (1 << pin_info->gpio_pin);
251+
}
252+
} else {
253+
// Output 0, it should always read back 0.
254+
// Configure it as output, despite of the output mode
255+
gpiobase->PORT[0].DR &= ~(1 << pin_info->gpio_pin);
256+
gpiobase->PORT[0].DDR |= (1 << pin_info->gpio_pin);
257+
}
258+
242259
if (isCachePin(pin) && isCachePinSetToOutput(pin)) {
243260
setCachePinState(pin, value);
244261
}

‎hal/src/rtl872x/i2c_hal.cpp

+28-14
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,14 @@ class I2cClass {
163163

164164
int end() {
165165
if (isEnabled()) {
166+
hal_gpio_config_t conf = {};
167+
conf.size = sizeof(conf);
168+
conf.version = HAL_GPIO_VERSION;
169+
conf.mode = OUTPUT_OPEN_DRAIN_PULLUP;
170+
conf.set_value = true;
171+
conf.value = 1;
172+
hal_gpio_configure(sclPin_, &conf, nullptr);
173+
hal_gpio_configure(sdaPin_, &conf, nullptr);
166174
if (i2cInitStruct_.I2CMaster == I2C_SLAVE_MODE) {
167175
InterruptDis(I2C0_IRQ_LP);
168176
InterruptUnRegister(I2C0_IRQ_LP);
@@ -195,24 +203,24 @@ class I2cClass {
195203
void reset() {
196204
end();
197205

198-
hal_gpio_mode(sclPin_, INPUT_PULLUP);
199206
// Just in case make sure that the pins are correctly configured (they should anyway be at this point)
200207
hal_gpio_config_t conf = {};
201208
conf.size = sizeof(conf);
202209
conf.version = HAL_GPIO_VERSION;
203210
conf.mode = OUTPUT_OPEN_DRAIN_PULLUP;
204211
conf.set_value = true;
205-
conf.value = hal_gpio_read(sclPin_);;
212+
conf.value = 1;
206213
hal_gpio_configure(sclPin_, &conf, nullptr);
214+
hal_gpio_configure(sdaPin_, &conf, nullptr);
215+
216+
// Check if slave is stretching the SCL
217+
if (!WAIT_TIMED(transConfig_.timeout_ms, hal_gpio_read(sclPin_) == 0)) {
218+
// We can't proceed because there is probably hardware issue.
219+
SPARK_ASSERT(false);
220+
}
207221

208222
// Generate up to 9 pulses on SCL to tell slave to release the bus
209223
for (int i = 0; i < 9; i++) {
210-
conf.value = 1;
211-
hal_gpio_configure(sdaPin_, &conf, nullptr);
212-
hal_gpio_write(sdaPin_, 1);
213-
HAL_Delay_Microseconds(50);
214-
215-
hal_gpio_mode(sdaPin_, INPUT_PULLUP);
216224
if (hal_gpio_read(sdaPin_) == 0) {
217225
hal_gpio_write(sclPin_, 0);
218226
HAL_Delay_Microseconds(50);
@@ -363,14 +371,20 @@ class I2cClass {
363371
if (quantity == 0) {
364372
// Clear flags
365373
uint32_t temp = i2cDev_->IC_CLR_TX_ABRT;
374+
temp = i2cDev_->IC_CLR_STOP_DET;
366375
(void)temp;
367-
if (i2cDev_->IC_TX_ABRT_SOURCE & 0x00000001) {
376+
if ((i2cDev_->IC_TX_ABRT_SOURCE & BIT_IC_TX_ABRT_SOURCE_ABRT_7B_ADDR_NOACK)
377+
|| (i2cDev_->IC_RAW_INTR_STAT & BIT_IC_RAW_INTR_STAT_STOP_DET)) {
368378
return SYSTEM_ERROR_I2C_ABORT;
369379
}
370380
// Send the slave address only
371-
i2cDev_->IC_DATA_CMD = (transConfig_.address << 1) | (1 << 11);
372-
HAL_Delay_Milliseconds(5);
373-
if (i2cDev_->IC_TX_ABRT_SOURCE & 0x00000001) {
381+
i2cDev_->IC_DATA_CMD = (transConfig_.address << 1) | BIT_CTRL_IC_DATA_CMD_NULLDATA | BIT_CTRL_IC_DATA_CMD_STOP;
382+
// If slave is not detected, the STOP_DET bit won't be set, and the TX_ABRT is set instead.
383+
if (!WAIT_TIMED(transConfig_.timeout_ms, ((i2cDev_->IC_TX_ABRT_SOURCE & BIT_IC_TX_ABRT_SOURCE_ABRT_7B_ADDR_NOACK) == 0)
384+
&& ((i2cDev_->IC_RAW_INTR_STAT & BIT_IC_RAW_INTR_STAT_STOP_DET) == 0))) {
385+
return SYSTEM_ERROR_I2C_TX_ADDR_TIMEOUT;
386+
}
387+
if (i2cDev_->IC_TX_ABRT_SOURCE & BIT_IC_TX_ABRT_SOURCE_ABRT_7B_ADDR_NOACK) {
374388
return SYSTEM_ERROR_I2C_ABORT;
375389
}
376390
return SYSTEM_ERROR_NONE;
@@ -388,10 +402,10 @@ class I2cClass {
388402
if(i >= quantity - 1) {
389403
if (stop) {
390404
// Generate stop signal
391-
i2cDev_->IC_DATA_CMD = data | (1 << 9);
405+
i2cDev_->IC_DATA_CMD = data | BIT_CTRL_IC_DATA_CMD_STOP;
392406
} else {
393407
// Generate restart signal
394-
i2cDev_->IC_DATA_CMD = data | (1 << 10);
408+
i2cDev_->IC_DATA_CMD = data | BIT_CTRL_IC_DATA_CMD_RESTART;
395409
}
396410
} else {
397411
// The address will be sent before sending the first data byte

‎user/tests/wiring/no_fixture/i2c.cpp

+12-21
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,15 @@ class SoftWire {
4747

4848
void init() {
4949
hal_i2c_end(i2c_, nullptr);
50-
pinMode(sda_, OUTPUT_OPEN_DRAIN_PULLUP);
51-
pinMode(scl_, OUTPUT_OPEN_DRAIN_PULLUP);
50+
hal_gpio_config_t conf = {
51+
.size = sizeof(conf),
52+
.version = HAL_GPIO_VERSION,
53+
.mode = OUTPUT_OPEN_DRAIN_PULLUP,
54+
.set_value = true,
55+
.value = 1
56+
};
57+
hal_gpio_configure(sda_, &conf, nullptr);
58+
hal_gpio_configure(scl_, &conf, nullptr);
5259
}
5360

5461
int transmit(const uint8_t* data, const WireTransmission& transmission, bool abort = false, size_t abortBitAfterAddress = 0, bool abortAck = false) {
@@ -119,20 +126,8 @@ class SoftWire {
119126
}
120127

121128
private:
122-
void pinMode(hal_pin_t pin, PinMode mode, bool val = 1) {
123-
hal_gpio_config_t conf = {
124-
.size = sizeof(conf),
125-
.version = HAL_GPIO_VERSION,
126-
.mode = mode,
127-
.set_value = true,
128-
.value = val
129-
};
130-
hal_gpio_configure(pin, &conf, nullptr);
131-
}
132-
133129
void startCondition() {
134130
Log.info("start");
135-
pinMode(sda_, OUTPUT_OPEN_DRAIN_PULLUP);
136131
hal_gpio_write(sda_, 0);
137132
HAL_Delay_Microseconds(50);
138133
hal_gpio_write(scl_, 0);
@@ -141,7 +136,6 @@ class SoftWire {
141136

142137
void stopCondition() {
143138
Log.info("stop");
144-
pinMode(sda_, OUTPUT_OPEN_DRAIN_PULLUP);
145139
hal_gpio_write(sda_, 0);
146140
HAL_Delay_Microseconds(50);
147141
hal_gpio_write(scl_, 1);
@@ -154,7 +148,6 @@ class SoftWire {
154148
Log.info("clock out %d bits (%02x)", bits, data);
155149
uint8_t res = 0x00;
156150
for (size_t i = 0; i < bits; i++) {
157-
pinMode(sda_, OUTPUT_OPEN_DRAIN_PULLUP);
158151
hal_gpio_write(sda_, data & 0x80);
159152
res |= hal_gpio_read(sda_) << (8 - i - 1);
160153
hal_gpio_write(scl_, 1);
@@ -169,8 +162,8 @@ class SoftWire {
169162
uint8_t clockByteIn(size_t bits = 8) {
170163
Log.info("clocking in %d bits", bits);
171164
uint8_t data = 0x00;
172-
pinMode(sda_, INPUT_PULLUP);
173165
while (bits-- > 0) {
166+
hal_gpio_write(sda_, 1);
174167
hal_gpio_write(scl_, 1);
175168
HAL_Delay_Microseconds(50);
176169
data |= (hal_gpio_read(sda_) & 0x01) << bits;
@@ -182,14 +175,13 @@ class SoftWire {
182175
}
183176

184177
int readAck() {
185-
pinMode(sda_, INPUT_PULLUP);
178+
hal_gpio_write(sda_, 1);
186179
hal_gpio_write(scl_, 1);
187180
HAL_Delay_Microseconds(50);
188181
bool ack = !hal_gpio_read(sda_);
189182
hal_gpio_write(scl_, 0);
190183
HAL_Delay_Microseconds(50);
191184
Log.info("read ack %d", ack);
192-
pinMode(sda_, OUTPUT_OPEN_DRAIN_PULLUP);
193185
hal_gpio_write(sda_, 0);
194186
if (!ack) {
195187
return SYSTEM_ERROR_PROTOCOL;
@@ -199,7 +191,6 @@ class SoftWire {
199191

200192
int ackOut(bool ack) {
201193
Log.info("out ack %d", ack);
202-
pinMode(sda_, OUTPUT_OPEN_DRAIN_PULLUP);
203194
hal_gpio_write(sda_, !ack);
204195
hal_gpio_write(scl_, 1);
205196
HAL_Delay_Microseconds(50);
@@ -375,8 +366,8 @@ test(I2C_07_bus_reset_is_not_destructive) {
375366
for (int i = 0; i <= 3 * 9 - 2 /* ignore full write without ack bit and full write with ack bit */; i++) {
376367
wire.init();
377368
assertMoreOrEqual(wire.transmit(txBuf, WireTransmission(MAX17043_ADDRESS).quantity(3), true /* abort */, i, true), 0);
378-
hal_i2c_reset(HAL_PLATFORM_FUELGAUGE_MAX17043_I2C, 0, nullptr);
379369
fuel.begin();
370+
hal_i2c_reset(HAL_PLATFORM_FUELGAUGE_MAX17043_I2C, 0, nullptr);
380371
memset(buf, 0xff, sizeof(buf));
381372
assertEqual(0, fuel.readConfigRegister(buf[0], buf[1]));
382373
config = buf[0] << 8 | buf[1];

0 commit comments

Comments
 (0)
Please sign in to comment.