Other Parts Discussed in Thread: SYSCONFIG, TIMAC
Tool/software:
So I've been staring myself blind here, and was hoping someone can shed some light/confirm my suspicions of a potential bug.
When I build a ZNP project, lets say we use the following example, https://github.com/TexasInstruments/simplelink-zstack-examples/blob/main/examples/rtos/CC1352P_2_LAUNCHXL/zstack/znp/README.html#L72 which is sadly not very readable as it's pure HTML, but bare with me. The linked line speaks of configuring the example using sysconfig. This is important for later.
Also mentioned in the same document at line 100, how to communicate with ZigBee Network Processor, e.g. 115200 no flow-control. This is of course as expected, since this is what the defaults of the syscfg settings (and the hardcoded defaults) are.
Another thing of importance, is to notice that in the projectspec, a define is set to tell the build to use the UART for the (ZigBee) Network Processor Interface https://github.com/TexasInstruments/simplelink-zstack-examples/blob/main/examples/rtos/CC1352P_2_LAUNCHXL/zstack/znp/tirtos7/ticlang/znp_CC1352P_2_LAUNCHXL_tirtos7_ticlang.projectspec#L30
The example is of course based off the SDK, and my first assumption now is that, the 'main' entrypoint of our application is somewhere in the zstack/znp SDK directory. Here is also determined how we communicate to the outside world, with the previously mentioned NPI_USE_UART define. To dumb it extremely (and incorrectly, I am aware) down, I expect something like:
```C
void main(void) {
do_zigbee_core_stuff();
NPIUART_writetransport(zigbee_data);
}
```
Looking at the NPIUART three things stand out.
First, we setup the default parameters for the UART2, https://github.com/TexasInstruments/simplelink-lowpower-f2-sdk/blob/d216a1abc94460e1ed53c2577da0302e93023c48/source/ti/zstack/npi/npi_tl_uart.c#L139 which is a hardcoded table https://github.com/TexasInstruments/simplelink-lowpower-f2-sdk/blob/d216a1abc94460e1ed53c2577da0302e93023c48/source/ti/drivers/UART2.c#L50 and just assigned to params https://github.com/TexasInstruments/simplelink-lowpower-f2-sdk/blob/d216a1abc94460e1ed53c2577da0302e93023c48/source/ti/drivers/UART2.c#L105 , but not relevant (at least not the baudrate, it gets overwritten below)
Second, NPIUART calls DISPLAY_UART to send out data, https://github.com/TexasInstruments/simplelink-lowpower-f2-sdk/blob/d216a1abc94460e1ed53c2577da0302e93023c48/source/ti/zstack/npi/npi_tl_uart.c#L157 which also makes sense, there's no UART setup or configured here.
The third thing that is odd, is that the baudrate parameters are hard-coded to a define https://github.com/TexasInstruments/simplelink-lowpower-f2-sdk/blob/d216a1abc94460e1ed53c2577da0302e93023c48/source/ti/zstack/npi/npi_tl_uart.c#L142 which is set here https://github.com/TexasInstruments/simplelink-lowpower-f2-sdk/blob/d216a1abc94460e1ed53c2577da0302e93023c48/source/ti/zstack/npi/npi_tl_uart.h#L66. So if it is not defined (as is our case from our projectspec file, it will always be hardcoded to either a FPGA favorable rate, or the expected 115200. I haven't figoured out what `HOST_CONFIG` is about however, but seems to be irrelevant. We are never using the FPGA define, as stuff would break everywhere, nor is `HOST_CONFIG` relevant for non-FPGA platforms. But it overwrites the previously initialized copied values.
Anyway, so far things are starting to trickle down, from main, to NPI where https://github.com/TexasInstruments/simplelink-lowpower-f2-sdk/blob/d216a1abc94460e1ed53c2577da0302e93023c48/source/ti/drivers/uart2/UART2CC26X2.c#L358 UART_Open is called with DISPLAY_UART as argument, just to indicate which of the display uarts to use, this is generated from sysconfig, more on this in a bit, and the params, which where hardcoded to defines (and enums) as part of the NPI_UART_init https://github.com/TexasInstruments/simplelink-lowpower-f2-sdk/blob/d216a1abc94460e1ed53c2577da0302e93023c48/source/ti/zstack/npi/npi_tl_uart.c#L131. This is problematic of course, because if we have hardcoded initialization parameters ...
Importantly it is to note, that the display config and its accompaning UART is generated from this template https://github.com/TexasInstruments/simplelink-lowpower-f2-sdk/blob/d216a1abc94460e1ed53c2577da0302e93023c48/source/ti/display/.meta/Display.Board.c.xdt which gets its input from sysconfig, and generates HWAttributes structures, for the display uart and it's underyling CC26x2 UART2, which *store* the baudrate and flowcontrol (and pin configuration). This then generates the `ti_drivers_config.c` file to be consumed by UART2_Open.
Within UART2_Open, called by NPIUART_Init(), which passes its own list of parameters, we copy the NPI parameters to the UART2CC26X driver 'object' (they are no longer parameters or hardware attributes :p) https://github.com/TexasInstruments/simplelink-lowpower-f2-sdk/blob/d216a1abc94460e1ed53c2577da0302e93023c48/source/ti/drivers/uart2/UART2CC26X2.c#L410 So now, object->baudRate is set to the hardcoded define of NPIUART NPI_UART_BR, e.g. 115200. Funnily enough, some booleans are hardcoded here, maybe the NPIUart doesn't even set them, or these values are ignored for our chip ...
Also our IO pins are setup from here https://github.com/TexasInstruments/simplelink-lowpower-f2-sdk/blob/d216a1abc94460e1ed53c2577da0302e93023c48/source/ti/drivers/uart2/UART2CC26X2.c#L447 which does correctly take into account our flow-control pins. https://github.com/TexasInstruments/simplelink-lowpower-f2-sdk/blob/d216a1abc94460e1ed53c2577da0302e93023c48/source/ti/drivers/uart2/UART2CC26X2.c#L1149 The variable comes from the previously mentioned Hardware Attributes, as do the pin configurations.
The baudRate is setup in the drivers UART_IinitHW() https://github.com/TexasInstruments/simplelink-lowpower-f2-sdk/blob/d216a1abc94460e1ed53c2577da0302e93023c48/source/ti/drivers/uart2/UART2CC26X2.c#L1087 which takes the copied hardcoded NPI values.
So where does the `ti_drivers_config.c` UART config go? I think the culprit is here, https://github.com/TexasInstruments/simplelink-lowpower-f2-sdk/blob/d216a1abc94460e1ed53c2577da0302e93023c48/source/ti/drivers/uart2/UART2CC26X2.c#L1089 which takes the 'object' baudrate, ignoring the hwAttrs baudRate. During init, this should have been checked, if setup or not. And only use the znp value if nothing is setup. Alternativly, the ZNP stack could define a MAX baudrate instead, but that would be a bigger change. Using a Define (USE_SYSCONFIG) would also work, but more defines is usually not a great idea :)
Comming back to the flowControl story, I have a rather interesting SonOff dongle, which has a switch for flowControl. The switch either connects the RTS/CTS pins to the CPN2102 UART chip, or, and not 100% sure what happens there yet, pulls them up/down to a preconfigured state. It could be because of that, if the stack is built with flow control enabled, and the switch is set to 'off' (pulling the RTS/CTS to their preconfigured states) that the znp stack always gets a positive result on those pins, and sends out data anyway. For 115200 there should be no difference thus whether flow control is enabled or not. On the other side of the link, it would of course matter what the state of the switch is. This could be the reason that hardware flow control _appears_ to do nothing, when in fact, it's working as expected, just being faked/ignored. I haven't probed the signal with a scope, but that's more to do with the tiny pins and pads ;) But could be that while pins and pads are setup for flow control, the chip is simply not 'enabling' flow-contorl, just connecting the pins. I haven't dug that deep there.
So does my story make some sense? Is this a bug, feature, expected behavior?