I now have the scenario where the following code generates a HardFault:
60086e76 <_lx_nor_flash_driver_write>:
60086e76: b5f8 push {r3, r4, r5, r6, r7, lr}
60086e78: af00 add r7, sp, #0
60086e7a: 4686 mov lr, r0
60086e7c: 4608 mov r0, r1
60086e7e: 4611 mov r1, r2
60086e80: 461a mov r2, r3 <---- HardFault happens here
Before the PUSH instruction the registers look like this:

and before the MOV instruction that triggers the fault the registers look like this:

I don't see any issues:
- Before the PUSH instruction LR has the address + 1 to the instruction that called BL to branch to _lx_nor_flash_driver_write
- PC is correct
- SP matches PSP
- XPSR has bit 24 set, indicating Thumb mode is active
- All instructions are on addresses that are 2-byte aligned, as required by Thumb
I've disabled all interrupts, and the ThreadX thread from which this is running is the only thread that's been created at this point, and it's the first code the thread runs. The thread has 64KiB of stack [0x2026db70, 0x2027db70] and as the images show the SP is still close to the top of the stack before the push (0x2027d998).
If I enter _lx_nor_flash_driver_write from the source code view and step over the initialization of the function call I get a HardFault, but if I step over individual instruction from the disassembly view it seems the core has crashed, as I'm unable to step over the MOV instruction where the fault points to, and I don't get into our HardFault_Handler...the system seems to have hung.
As previously mentioned, adding or removing other seemingly unrelated code can make the HardFault go away and come back, even without the address of the instruction where the HardFault occurs changing.