cancel
Showing results for 
Search instead for 
Did you mean: 

ST7 instability with AN1905 sensorless BLDC motor control software

jon239955
Associate II
Posted on August 13, 2010 at 19:07

Hi everyone,

I apologize in advance for what is bound to be a very generic-sounding question, but I've been staring at this bug for a week and feel like posting here might at the very least be cathartic :)

I'm using the AK-ST7FMC motor control kit with the 3-phase sensorless brushless DC motor control software library described in AN-19 The chip itself is an ST7FMC2N6B6, and I'm using the Cosmic C compiler (in small memory model mode), STVD7, and an inDART-STX. I am new to the chip, the compiler, the emulator...everything.

I've modified the software to start and stop the motor periodically. I use Timer A to generate an interrupt at a selectable period. From the Timer A ISR I invoke a callback function via a function pointer that in turn sets a flag indicating that it's time to start the motor. The program's main loop sees the flag and calls MTC_StartMotor. The D/C event ISR increments a counter with each autoswitched commutation. The main loop periodically samples the counter and calls MTC_StopMotor when the counter passes a target threshold. The sequence then repeats.

My problem is that occasionally the system will stop. As near as I can tell, this happens during motor startup, between the time MTC_StartMotor is called and the time that the D/C event ISR enters autoswitched mode. The system stops responding to keypresses and is just generally borked until a reset. I believe that I've verified (through toggling a debug pin attached to a scope) that the D/C event ISR stops firing, the Timer B and Timer A ISRs stop firing, the main loop stops looping...in short, the chip is either executing code off in the weeds, or it is being held in reset, or something I don't understand is happening. This occurs as long as the firmware is running from flash, whether the system is connected to the inDART or not.

It is interesting to note that I've not been able to reproduce this issue when the code is being run on the chip directly from STVD7 via the inDART. That doesn't mean it's not there, though.

So, I'm not asking you to solve this problem :) What I am asking for, however, is any advice that you might offer me as I attempt to solve this problem myself. I've reviewed my code. I've ensured that writes to variables and function pointers that are accessed via ISR occur with interrupts disabled. I've ensured that no functions are called from both ISRs and ''main'' program execution, because as I understand it function reentrancy is not supported given my configuration. I've used the debugger to ensure that tables and function pointers have the appropriate contents. I've reviewed the generated assembly language, examined the linker map file, and read up on the Cosmic C compiler and the ST7's memory models, calling conventions, and etcetera. Unfortunately, I'm still stuck.

I suspect one of several things are happening: an invalid pointer is being dereferenced either as part of a function call or as part of a table lookup, an ISR is firing and not resetting its flag, causing it to hog forever, something is getting fouled up ''stack''-wise (although as I understand it there might not be a call stack per se), or the chip is winding up in reset or power-down or something.

Being unfamiliar with this particular chip and toolchain, and being in somewhat of a hurry to put this bug behind me, my question (at last) is:

What would you do if you were me? How would you go about finding the root cause of this issue? Does anything that I've described raise a red flag based on your knowledge of the chip, the compiler, the demo kit, or my software design?

Any help that you could provide would be greatly, greatly appreciated, and I thank you in advance.

1 REPLY 1
jon239955
Associate II
Posted on August 16, 2010 at 23:52

Hi again,

I'm getting close to a culprit, I think, but am still struggling with my unfamiliarity with the chip, compiler, etcetera.  From everything I can tell, this function is occasionally entered but is never exited when it is called from MTC_StartMotor, in turn called from main:

void PORTS_BothLedOff(void)

{

    Flag_port &= (u8)~BothLedFlash;          // stop flashing LED if previously selected

    PBDDR &= (u8)~Led;         //PB7 Floating Input

    PBOR  &= (u8)~Led;

}

Here is the disassembly:

474                     ; 168 void PORTS_BothLedOff(void)

474                     ; 169 {

475                     .text:    section    .text,new

476  0000               _PORTS_BothLedOff:

479                     ; 170     Flag_port &= (u8)~BothLedFlash;          // stop flashing LED if previously selected

481  0000 c60001            ld    a,_Flag_port

482  0003 a4fc              and    a,#252

483  0005 c70001            ld    _Flag_port,a

484                     ; 172     PBDDR &= (u8)~Led;         //PB7 Floating Input

486  0008 1f00              bres    _PBDDR,#7

487                     ; 173     PBOR  &= (u8)~Led;

489  000a 1f00              bres    _PBOR,#7

490                     ; 174 }

493  000c 81                ret   

I've verified this by setting a debug pin right before this function is called and clearing it when the function returns.  I see the pin set on my scope and never cleared, always coincident with the lockup I describe in my previous post.

My question: is there anything within this block of code that appears fragile or subject to disaster if it is interrupted or if code executing immediately before it doesn't behave itself? 

I'm using the Cosmic C compiler's small memory model and I am not nesting interrupts that I am aware of.  I do have some ISRs that do things like invoke callbacks through function pointers and perform arithmetic on 16-bit integers.  I have no special adornment (e.g. @nosvf, @stack, @nostack, etcetera) on any of my ISRs. 

As near as I can tell this function is only called from the main flow and is not also invoked from within an ISR.  Flag_port is read from within a different ISR but I haven't yet been able to determine if that ISR is firing while inside the function above (maybe that's something to try).  Regardless the manipulation of Flag_port done in PORTS_BothLedOff seems to be safe even if it is interrupted as it's done in the accumulator register.

My leading theory is that some previous function or ISR is messing with the real stack, the simulated stack, or the compiler's scratch memory in such a way that the ret instruction is jumping off into the weeds, but I'm really grasping at straws.

Any help that anyone could provide would be greatly, greatly appreciated.