Hi Mark,
I agree with what you say above. It seems in this case, though, in starting with an example program, we're using a ton of code provided by NXP (even in this ridiculously simple example to toggle a GPIO). And, that code either directly or indirectly creates the conditions for a hard fault from the clock/UART settings.
In the example project (gpio_led_output), the 3rd function call in main is: BOARD_InitDebugConsole();
This, in turn, calls: DbgConsole_Init()
which calls: LOG_Init()
which calls: IO_Init()
which eventually calls: UART_Init()
inside UART_Init(), which is in the file "fsl_uart.c", it calculates your baud rate error, and if it is greater than 3%, the function immediately returns with a error code. The return value of that function is not checked, and thus the error code itself is not consequential. However, because the UART_Init() function returns as soon as it sees that the error is too high, it doesn't complete a bunch of other stuff to setup the UART.
The next function call directly after UART_Init() is UART_EnableTx(), this is in the file "fsl_io.c". The first thing this function attempts to do is enable the UART by enabling the bit in the C2 register: "base->C2 |= UART_C2_TE_MASK;"
Single stepping through the program, immediately after this line, you end up in the hard-fault handler.
I haven't dug into what registers are setup in the UART_Init() function AFTER the check on baud-rate error, but apparently the enabling of the transmitter requires one/some of those registers to be set correctly, otherwise you end up with a hard fault.
Thanks!
Ted