7 years, 5 months ago.

After merging USB CDC Serial, the SX1276Lib will fall into hardfault handler ?

I have verified the LoRa project with NUCLEO-F103RB/L053R8 and other NUCLEO boards. Now I am trying to port the projects into a low cost STM32F103C8 blue pill development board. The major difference is communication to host, from UART2 to USB on board. I used to doubt there is something wrong with USB stack with SX1276Lib, but now I figured out that SX1276Lib doesn't work well on STM32F103C8. Because all TX works well, but RX will failed and fall into a Hardfault handler.

Here is a log fo code and registers.

sx1276.cpp"

sx1276.cpp,  line 810, void SX1276::Rx( uint32_t timeout )

C code:

Write( REG_LR_INVERTIQ, ( ( Read( REG_LR_INVERTIQ ) & RFLR_INVERTIQ_TX_MASK & RFLR_INVERTIQ_RX_MASK ) | RFLR_INVERTIQ_RX_OFF | RFLR_INVERTIQ_TX_OFF ) );

Disassembly code:

LDR r0,[r4,#0x00]
MOVS r1,#0x33
LDR r2,[r0,#0x50]
MOV r0,r4
BLX r2

MACRO definitions:

REG_LR_INVERTIQ             0x33
RFLR_INVERTIQ_TX_MASK       0xFE
RFLR_INVERTIQ_RX_MASK       0xBF
RFLR_INVERTIQ_RX_OFF        0x00
RFLR_INVERTIQ_TX_OFF        0x01

The breakpoint will be hit twice, after POR, the main loop will call Radio.Rx(), it works well. After RX timeout, aka no RX signal received, the FSM will restart Radio.Rx(), during this SX1276::Rx() calls, the R2 will be loaded as 0x00000000, then BLX R2 will cause a hardfault. Aka. Radio.Read() or Radio.Write() functions are mis-leaded.

Obviously, the root cause is r0 is different before coming into this functions. And r0 points to some variables which is altered in the main loop, and causes hardfault anyway.

I am not familiar with Cortex core as I did in 8051. Its calling conventions, register arrangement and map to C++ class is not very straighforward.

Any help, hints are highly welcome. Thanks in advance.

1 Answer

7 years, 4 months ago.

Dear Kai Liu,

I am maintaining a own copy of the SX1276Lib called SX1276Generic.Lib with many important enhancements. Maybe my version resolves already something for you.

Regarding the HardFault hander. The ARM Cortex-M puts a on the stack a Frame with the registers. The PC points to the location where it crashed.

stack frame

struct StackFrame {
    unsigned int reg_r0;
    unsigned int reg_r1;
    unsigned int reg_r2;
    unsigned int reg_r3;
    unsigned int reg_r12;
    unsigned int reg_lr; /* Link register. */
    unsigned int reg_pc; /* Program counter. */
    unsigned int reg_psr;/* Program status register. */
};

I use Keil MDK and gcc/gdb for debugging.

Good luck. Helmut

Thanks, Helmut. I will download your library. You are very helpful. I will use hardfault handler in future code.

After struggling with hardfault, I finally find its root cause by a very stupid step by step code tracing. It is an obvious buffer pointer out of index. The pointer is out of range and changed the Radio.radio object's content.

Now USB and SX1276 have been merged successfully and I am moving on to build a LoRa USB modem with enclousure, I hope it could be used either in device and gateway with any PC/Linux SBC.

Thanks for your reply.

posted by Kai Liu 27 Jun 2017

Sounds very good, keep me informed about it. BTW: I have developed a complete peer to peer protocol with AES/SHA256 encryption using the SX1276 chip wich does not need any concentrator and can handle many nodes. However I need about 140kB Flash (RAM <20kB, depends on number of nodes) for the protocol. It would be too much for the F103, the STM32L4 is my preferred MCU series due to power savings.

posted by Helmut Tschemernjak 28 Jun 2017