cancel
Showing results for 
Search instead for 
Did you mean: 

Float Assignment Causing HardFault

Posted on November 09, 2017 at 21:27

Hello. I am trying to control a step motor with a driver like m542 stepper driver. I can control the rotation speed and direction of the motor. I'm working with STM32F4-Discovery to get prototype done. Everything was good when I tried to add some distance control functions. So, the step motor is 200 pulse/rev and I need to control some small size distances and the timers have capabilities about that. I created a struct and it just has five elements one of them is float.

I want to calculate the pulse ratio between motor and driver and send pulses due to the range. But I cannot assign any value to that float ratio element of struct. The core goes hard fault handler when I want to simple assignment to that variable like as; `STRUCT.fVAR = (float)40.0;`. Here is my struct and code which is causing the fault;

typedef enum

{

  Z = 0,

  Y1 = 1,

  Y2 = 2

}MSMD_AxesEnum_t;

typedef struct

{

  __IO MSMD_DirectionEnum_t dir;

  __IO int speed;

  __IO float sensitivity;

  __IO uint32_t driverPPR;

  __IO uint32_t motorPPR;

}MSMD_TypeDef_t;

__IO MSMD_TypeDef_t  MSMD[3]; // Using 3 different motor

static __inline void MSMD_CalculateRatio(MSMD_AxesEnum_t axis)

{

  if ((MSMD[axis].motorPPR != 0) && (MSMD[axis].driverPPR != 0))

  {

    /*

    HardFault occurred first here but I didn't understand why then I added a simple assignment line before calling this function in init.

    */

    MSMD[axis].sensitivity = ((float)MSMD[axis].motorPPR / (float)MSMD[axis].driverPPR);

  }

}

int MSMD_Init(MSMD_AxesEnum_t axis)

{

  /**

  **  Timer and GPIO initializations. They are working well I added the problematic part after check all the functionalities

  **/

  MSMD[axis].driverPPR = 40000;

  MSMD[axis].motorPPR = 200;

  MSMD[axis].sensitivity = (float)40.0; // Then HardFault occurred in here again.

  MSMD_CalculateRatio(axis);

}

I'm using Keil MDK 5.24 Plus edition and STM32F4-Discovery_FW_V1.1.0. And I checked the Fault Reports then saw the hard fault was forced. I understand that it is forced by another disabled fault handler and the NOCP bit is set in the UsageFault section. I'm adding the Fault Report screen image.

I didn't see any unusual thing on the SFRs and/or SP, PC.

EDIT: When I comment just these lines everything works well.

Thanks.

#stm32f4 #float #hardfault
4 REPLIES 4
Posted on November 09, 2017 at 21:53

Look at the instruction that is faulting. Look at a disassembly.

Make sure the FPU is enabled, code would frequently be in SystemInit() or in the Reset Handler

Make sure MSMD[axis].driverPPR is not ZERO, check for that before doing the division.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on November 09, 2017 at 22:20

Thanks

Turvey.Clive.002

‌ I'm checking the divider MSMD[axis].driverPPR before calculating. This is a compiler problem that I've seen. I didn't see any necessity about FPU enabling in SystemInit() or in the Reset Handler because I cannot assign simple constant assignment to a fload/double/long double variable and The Floating Point Hardware is selected as Single Precision in the Code Generation section of the Flash/Configure Flash Tools/Target menu. The weird thing is assignment line so I tried to check another settings in the project. I've looked the Target menu then saw the ARM compiler is selected defaultly

Use default compiler version 5 then changed it to

v5.06 update 5 (build 528) in Code Generation section. Now the code is working fine. There is no Hard Fault and the values are correct in calculation. This is a Keil issue I think. Or as you said the compiler that is used now is handling the FPU things itself. I'll try. Thanks again for quick reply.

Posted on November 10, 2017 at 01:06

>>

This is a Keil issue I think.

Well it should be easy enough to see exactly what the CPU is complaining about, then you'd know.

If the compiler uses FPU instructions your startup code must enable it, doesn't happen by itself. Different compilers might use push/pop s0/d0 register, or constants might be loaded into the FPU, others just use ARM registers.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on November 17, 2017 at 14:37

Thanks

Turvey.Clive.002

‌. I was trying to add USB device support to my project and finished it today then started to test both code and then it disappeared and I've added an enabling function before the hard-fault causing code. I don't know is it safe or not but working.

Also in the Programming Manual at the section FPU (page 237)

it is saying;

'Bits 23:20 CPn: [2n+1:2n] for n values 10 and Access privileges for coprocessor n. The possible

values of each field are:

0b00: Access denied. Any attempted access generates a NOCP UsageFault.

0b01: Privileged access only. An unprivileged access generates a NOCP fault.

0b10: Reserved. The result of any access is Unpredictable.

0b11: Full access.'

I'm accessing the CPACR register with using SBC. Here is my function to enable co-processor 0;

#define__SCB_CPACR_FPU_MSK 0x00300000

void EnableFPU(void)

{

__IO uint32_t __CPACR = SBC->CPACR;

__CPACR |=__SCB_CPACR_FPU_MSK;

SBC->CPACR = __CPACR;

}

I don't know which is necessary so enabled both first then try just CP0. It is enough again.

Thanks again.