Skip to content

Commit 1fad381

Browse files
committed
[RP2040] Allow any GPIO pin for RS485 direction pin
As I mentioned in issue #6310 while investigating that the Teensy port did not support RS485_dir pin on normal GPIO pins, I found that it was not implemented either as well on some other ports. So was curious to implement it for RP2040 using same approach as I did for the MIMXRT in the Pull Request #6328 That is I setup the specified pin as a normal GPIO pin in output mode and then when you do a write operation it sets the GPIO pin logically high, and when the write completes I set it logically low. Note: knowing when I can set it low can be tricky, as you need to make sure the full output has completed otherwise the data will be corrupted. I am using: uart_tx_wait_blocking(self->uart); Which looks like it is supposed to wait until the busy status is no longer set, which the Reference manual mentioned, but this is leaving the line logically set longer than I would like. however I have tried running it with my hacked up version of the Python Robotis DynamixelSDK and was able to talk to some AX servos. I did have to change the library slightly for the RP2040, as the library was erroring out when you did something like uart.read(5) and it timed out without receiving anything. The RP2040 returned None whereas I think the Teensy returned an empty set, which is what it looks like the PySerial original code expects. Not sure if anyone is interested in this, but thought i would put it out as PR and see.
1 parent b598ec0 commit 1fad381

File tree

2 files changed

+36
-5
lines changed

2 files changed

+36
-5
lines changed

ports/raspberrypi/common-hal/busio/UART.c

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,6 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
112112
mp_raise_ValueError(translate("Invalid buffer size"));
113113
}
114114

115-
if ((rs485_dir != NULL) || (rs485_invert)) {
116-
mp_raise_NotImplementedError(translate("RS485 Not yet supported on this device"));
117-
}
118-
119115
uint8_t uart_id = ((((tx != NULL) ? tx->number : rx->number) + 4) / 8) % NUM_UARTS;
120116

121117
if (uart_status[uart_id] != STATUS_FREE) {
@@ -126,6 +122,29 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
126122
self->rx_pin = pin_init(uart_id, rx, 1);
127123
self->cts_pin = pin_init(uart_id, cts, 2);
128124
self->rts_pin = pin_init(uart_id, rts, 3);
125+
126+
if (rs485_dir != NULL) {
127+
uint8_t pin = rs485_dir->number;
128+
self->rs485_dir_pin = pin;
129+
self->rs485_invert = rs485_invert;
130+
131+
gpio_init(pin);
132+
133+
claim_pin(rs485_dir);
134+
135+
gpio_disable_pulls(pin);
136+
137+
// Turn on "strong" pin driving (more current available).
138+
hw_write_masked(&padsbank0_hw->io[pin],
139+
PADS_BANK0_GPIO0_DRIVE_VALUE_12MA << PADS_BANK0_GPIO0_DRIVE_LSB,
140+
PADS_BANK0_GPIO0_DRIVE_BITS);
141+
142+
gpio_put(self->rs485_dir_pin, rs485_invert);
143+
gpio_set_dir(self->rs485_dir_pin, GPIO_OUT);
144+
} else {
145+
self->rs485_dir_pin = NO_PIN;
146+
}
147+
129148
uart_status[uart_id] = STATUS_BUSY;
130149

131150

@@ -179,10 +198,12 @@ void common_hal_busio_uart_deinit(busio_uart_obj_t *self) {
179198
reset_pin_number(self->rx_pin);
180199
reset_pin_number(self->cts_pin);
181200
reset_pin_number(self->rts_pin);
201+
reset_pin_number(self->rs485_dir_pin);
182202
self->tx_pin = NO_PIN;
183203
self->rx_pin = NO_PIN;
184204
self->cts_pin = NO_PIN;
185205
self->rts_pin = NO_PIN;
206+
self->rs485_dir_pin = NO_PIN;
186207
}
187208

188209
// Write characters.
@@ -191,6 +212,11 @@ size_t common_hal_busio_uart_write(busio_uart_obj_t *self, const uint8_t *data,
191212
mp_raise_ValueError(translate("No TX pin"));
192213
}
193214

215+
if (self->rs485_dir_pin != NO_PIN) {
216+
uart_tx_wait_blocking(self->uart);
217+
gpio_put(self->rs485_dir_pin, !self->rs485_invert);
218+
}
219+
194220
size_t left_to_write = len;
195221
while (left_to_write > 0) {
196222
while (uart_is_writable(self->uart) && left_to_write > 0) {
@@ -201,7 +227,10 @@ size_t common_hal_busio_uart_write(busio_uart_obj_t *self, const uint8_t *data,
201227
}
202228
RUN_BACKGROUND_TASKS;
203229
}
204-
230+
if (self->rs485_dir_pin != NO_PIN) {
231+
uart_tx_wait_blocking(self->uart);
232+
gpio_put(self->rs485_dir_pin, self->rs485_invert);
233+
}
205234
return len;
206235
}
207236

ports/raspberrypi/common-hal/busio/UART.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ typedef struct {
3737
uint8_t tx_pin;
3838
uint8_t rx_pin;
3939
uint8_t cts_pin;
40+
uint8_t rs485_dir_pin;
41+
bool rs485_invert;
4042
uint8_t rts_pin;
4143
uint8_t uart_id;
4244
uint8_t uart_irq_id;

0 commit comments

Comments
 (0)