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

UART initialization chooses incorrect interface if lower-numbered interface shares a pin #46

Open
UbiJCC opened this issue Dec 31, 2020 · 2 comments

Comments

@UbiJCC
Copy link

UbiJCC commented Dec 31, 2020

Description of defect

When attempting to initialize UART1 on certain pins (see below), instead UART0 is initialized to these pins, because they are present in PinMap_UART_TX and PinMap_UART_RX (in PeripheralPins.c) as UART_0 before the UART_1 entry.

AFFECTED PINS
(These are all pins that can function as either UART0 or UART1, and thus, cannot actually function as UART1)

TX    RX

      2
20    21
39    40

PeripheralPins.c:

/************UART***************/
const PinMap PinMap_UART_TX[] = {
	{AP3_PER_UART0_TX_1, UART_0, (uint32_t)&g_AP3_PER_UART0_TX_1},
	{AP3_PER_UART0_TX_7, UART_0, (uint32_t)&g_AP3_PER_UART0_TX_7},
	{AP3_PER_UART0_TX_16, UART_0, (uint32_t)&g_AP3_PER_UART0_TX_16},
	{AP3_PER_UART0_TX_20, UART_0, (uint32_t)&g_AP3_PER_UART0_TX_20},
	{AP3_PER_UART0_TX_22, UART_0, (uint32_t)&g_AP3_PER_UART0_TX_22},
	{AP3_PER_UART0_TX_26, UART_0, (uint32_t)&g_AP3_PER_UART0_TX_26},
	{AP3_PER_UART0_TX_28, UART_0, (uint32_t)&g_AP3_PER_UART0_TX_28},
	{AP3_PER_UART0_TX_39, UART_0, (uint32_t)&g_AP3_PER_UART0_TX_39}, <--- Pin 39 listed as UART_0
	{AP3_PER_UART0_TX_41, UART_0, (uint32_t)&g_AP3_PER_UART0_TX_41},
	{AP3_PER_UART0_TX_44, UART_0, (uint32_t)&g_AP3_PER_UART0_TX_44},
	{AP3_PER_UART0_TX_48, UART_0, (uint32_t)&g_AP3_PER_UART0_TX_48},
	{AP3_PER_UART1_TX_8, UART_1, (uint32_t)&g_AP3_PER_UART1_TX_8},
	{AP3_PER_UART1_TX_10, UART_1, (uint32_t)&g_AP3_PER_UART1_TX_10},
	{AP3_PER_UART1_TX_12, UART_1, (uint32_t)&g_AP3_PER_UART1_TX_12},
	{AP3_PER_UART1_TX_14, UART_1, (uint32_t)&g_AP3_PER_UART1_TX_14},
	{AP3_PER_UART1_TX_18, UART_1, (uint32_t)&g_AP3_PER_UART1_TX_18},
	{AP3_PER_UART1_TX_20, UART_1, (uint32_t)&g_AP3_PER_UART1_TX_20},
	{AP3_PER_UART1_TX_24, UART_1, (uint32_t)&g_AP3_PER_UART1_TX_24},
	{AP3_PER_UART1_TX_39, UART_1, (uint32_t)&g_AP3_PER_UART1_TX_39}, <-- Pin 39 listed as UART_1, but impossible to actually use
#if defined (AM_PACKAGE_BGA)
	{AP3_PER_UART0_TX_30, UART_0, (uint32_t)&g_AP3_PER_UART0_TX_30},
	{AP3_PER_UART1_TX_35, UART_1, (uint32_t)&g_AP3_PER_UART1_TX_35},
	{AP3_PER_UART1_TX_37, UART_1, (uint32_t)&g_AP3_PER_UART1_TX_37},
	{AP3_PER_UART1_TX_42, UART_1, (uint32_t)&g_AP3_PER_UART1_TX_42},
	{AP3_PER_UART1_TX_46, UART_1, (uint32_t)&g_AP3_PER_UART1_TX_46},
#endif // defined (AM_PACKAGE_BGA)
	{NC, NC, 0}
};

const PinMap PinMap_UART_RX[] = {
	{AP3_PER_UART0_RX_2, UART_0, (uint32_t)&g_AP3_PER_UART0_RX_2},
	{AP3_PER_UART0_RX_11, UART_0, (uint32_t)&g_AP3_PER_UART0_RX_11},
	{AP3_PER_UART0_RX_17, UART_0, (uint32_t)&g_AP3_PER_UART0_RX_17},
	{AP3_PER_UART0_RX_21, UART_0, (uint32_t)&g_AP3_PER_UART0_RX_21},
	{AP3_PER_UART0_RX_23, UART_0, (uint32_t)&g_AP3_PER_UART0_RX_23},
	{AP3_PER_UART0_RX_27, UART_0, (uint32_t)&g_AP3_PER_UART0_RX_27},
	{AP3_PER_UART0_RX_29, UART_0, (uint32_t)&g_AP3_PER_UART0_RX_29},
	{AP3_PER_UART0_RX_40, UART_0, (uint32_t)&g_AP3_PER_UART0_RX_40}, <-- Pin 40 listed as UART_0
	{AP3_PER_UART0_RX_49, UART_0, (uint32_t)&g_AP3_PER_UART0_RX_49},
	{AP3_PER_UART1_RX_2, UART_1, (uint32_t)&g_AP3_PER_UART1_RX_2},
	{AP3_PER_UART1_RX_4, UART_1, (uint32_t)&g_AP3_PER_UART1_RX_4},
	{AP3_PER_UART1_RX_9, UART_1, (uint32_t)&g_AP3_PER_UART1_RX_9},
	{AP3_PER_UART1_RX_13, UART_1, (uint32_t)&g_AP3_PER_UART1_RX_13},
	{AP3_PER_UART1_RX_15, UART_1, (uint32_t)&g_AP3_PER_UART1_RX_15},
	{AP3_PER_UART1_RX_19, UART_1, (uint32_t)&g_AP3_PER_UART1_RX_19},
	{AP3_PER_UART1_RX_21, UART_1, (uint32_t)&g_AP3_PER_UART1_RX_21},
	{AP3_PER_UART1_RX_25, UART_1, (uint32_t)&g_AP3_PER_UART1_RX_25},
	{AP3_PER_UART1_RX_40, UART_1, (uint32_t)&g_AP3_PER_UART1_RX_40}, <-- pin 40 listed as UART_1
	{AP3_PER_UART1_RX_47, UART_1, (uint32_t)&g_AP3_PER_UART1_RX_47},
#if defined (AM_PACKAGE_BGA)
	{AP3_PER_UART0_RX_31, UART_0, (uint32_t)&g_AP3_PER_UART0_RX_31},
	{AP3_PER_UART0_RX_34, UART_0, (uint32_t)&g_AP3_PER_UART0_RX_34},
	{AP3_PER_UART0_RX_45, UART_0, (uint32_t)&g_AP3_PER_UART0_RX_45},
	{AP3_PER_UART1_RX_36, UART_1, (uint32_t)&g_AP3_PER_UART1_RX_36},
	{AP3_PER_UART1_RX_38, UART_1, (uint32_t)&g_AP3_PER_UART1_RX_38},
	{AP3_PER_UART1_RX_43, UART_1, (uint32_t)&g_AP3_PER_UART1_RX_43},
#endif // defined (AM_PACKAGE_BGA)
	{NC, NC, 0}
};

This happens because in serial_api.c, inside serial_init(...), the UART interface to initialize is determined by the following code:

serial_api.c:

  UARTName uart_tx = (UARTName)pinmap_peripheral(tx, serial_tx_pinmap());
  UARTName uart_rx = (UARTName)pinmap_peripheral(rx, serial_rx_pinmap());
  UARTName uart = (UARTName)pinmap_merge(uart_tx, uart_rx);

pinmap_peripheral() does a simple scan through the passed array (here, PinMap_UART_TX and PinMap_UART_RX), starting from the first index.

Therefore, for pins 39 and 40, it will always select UART0, because that is what is present in the array first.

Furthermore, because the Arduino core caches the mbed OS, it is NOT sufficient to simply comment out those lines or change the file, as it will not be recompiled. A full recompile of the mbed OS is necessary, but this is a complete hack when working with Arduino.

Target(s) affected by this defect ?

All; this issue is present in the TARGET_APOLLO3/device folder, which seems to take effect for any Apollo 3 sub-target.

How is this defect reproduced ?

Attempt to initialize UART1 on any of the above pins. The pins will instead be initialized as UART0.

Possible Solutions

I can think of a few ways to solve this issue, though I must admit: I'm quite new to this codebase, and I've been struggling with this problem for weeks. It took me a long time to find the actual issue because it's just... a lot to familiarize myself with. I say this just to indicate that I'm likely missing a very obvious, natural way to fix this.

Proper BSP usage

It seems that right now, the BSP for any individual target is being used in multiple places, its definitions referenced (manually?) in others, and is being (almost completely?) overruled by the following files in TARGET_APOLLO3/device:

  • PeripheralPinConfigs.c/h
    • These seems to be am_bsp_pins.c/h with no changes to content
  • PeripheralPins.c
    • This seems to be a manually-written bridge between Mbed and Apollo3, written specifically against PeripheralPinConfigs, as opposed to the developer-provided BSP

These seem to be the files that actually dictate the BSP that is used by mbed OS, and it's a BSP that seems to be "every pin can do everything it can do". Which seems reasonable, except for bugs like this.

Is there an easy way to allow developers to provide their own BSP? It's possible now, but you need to recompile the mbed os library. Currently, I'll need to maintain a fork of this library to use my own BSP.

@UbiJCC UbiJCC changed the title UART interface cannot be initialized if lower-numbered interface shares a pin UART initialization chooses incorrect interface if lower-numbered interface shares a pin Dec 31, 2020
@gimasi
Copy link

gimasi commented Sep 21, 2022

Hello,
I am having the same issue and after a couple of days struggling I came across your post.
Still trying to figure out how to fix it.
Will update if I manage...
Massimo

@paulvha
Copy link

paulvha commented Nov 24, 2022

only now see this posting, to bad as wasting time could have been prevented. Also see sparkfun/Arduino_Apollo3#474

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants