This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

increase code speed for execution

Other Parts Discussed in Thread: CONTROLSUITE, MOTORWARE, DRV8301

Hi everyone,

I am using F28027 Launchpad for a motor control application involving a position estimation algrithm developed by myself. I managed to program the codes in ISR which is called and executed during every CPU interrupt triggered by epwm.

At this moment, my code has only few lines. I use 6 ADCs for collecting necessary voltage and current signals, and 3 Clarke transform modules to convert three phase signals into quantities in quadrature. Then the Clarke outputs are fed into a position estimation block I programed myself. The position estimation involves some square root calculations and some inverse trignometric calculation.

I tested the speed of executing ISR by toggling a GPIO each time ISR is called. I found that it requires a period of approx.15 micro-seconds for each ISR, which means my ISR interrupt frequency is limited to about 6kHz.

I am wondering if it is possible to speed up my code a little bit, for example change the way ADC are triggered or some other optimization of math operations.Does anyone have any ideas please?

Thank you very much.

Jingzhe

  • Hi!

    And what about loading of time-critical code in RAM? Did you try?

    Regards,

    Igor

  • Hi Igor,

    Actually I think I loaded all the codes into flash. 

    That sounds a good idea, but how exactly do I load a part of my code into RAM while the other parts remain in flash?

    Thank you.

    Jingzhe

  • Hi!

    I would recommend you this material 3884.TI_Copying Compiler Sections From Flash to RAM.pdf.

    Regards,

    Igor

  • Thanks Igor, I'll give it a try.

  • you should have your interrupt start on your ADC values being ready, not the ePWM timer, else your feedback calculations will be processed with the data from the previous cycle.

    i'd make sure your Flash wait states are set correctly.

    I'd use IQMath, and tables from the ROM.

    15us isn't too bad for a full control loop system, it's similar to our sensorless SMO based systems in controlSUITE and about half of our high performance InstaSPIN-FOC solution. 15us is only 15% of a 10KHz control loop...where are you getting 6 KHz limit?

     

  • Hi Chris,

    I'm sorry, the period is 150us. I've made a mistake in the post.

    Could you please give a bit details or examples like how to start the interrupt based on ADC triggering and set flash wait state etc.? I am really not a programming type person, my specialization is in electrical machines.

    Thank you.

    Jingzhe

  • Jingzhe,

    Wow, 150us, that is quite poor.  I would suspect you have an extreme amount of wasted cycles.

    If you aren't familiar with embedded software I think this is going to be challening for you either way. Have you considered graphical code development based on VisSim or Mathworks Embedded Target?

    We have motor system examples in controlSUITE (mostly using F28035) and MotorWare (F28027F support, hardware uses controlCARD, LaunchPad in a couple months) that you can use.  The controlSUITE is a simpler SW approach and probably better suited to your experience level.  The MotorWare is more tailored to software engineers and uses our InstaSPIN-FOC control structure, which may be confusing if you want to do all of your own algorithms.

     

     

  • Hi Chris,

    Actually I've been using example projects from controlSUITE, especially the 2xMotor and PMAC sensor less control projects as base to develope my own code. I believe most of my codes is similar to them, I just tailored the innovative parts. This is why I'm confused that which part is going wrong that caused my codes to be so slow. What I'm concerned is that the execution of my ISR is too long, does it have anything to do with triggering or the other possibilities you mentioned?

    Thanks,

    Jingzhe

  • I am pretty sure that the 2xMOTOR uses the PWM trigger instead of the ADC end of conversion.

    No, that's not causing your cycle issues, it's just something I wanted to note.

    I don't know what your innovative code is, but it is highly inefficient the way it is written/compiled. It's impossible to say what is happening with the information we have now.

    debugging your software will be the next step. you may want to start with using some GPIO pins to do some timing analysis of the major pieces of your code and see where the problem is.

     

     

  • Hi Chris,

    Thank you very much for your assistance. I will definitely try  to improve my code as you suggested. At this moment I am trying to figure out the reason of my slow ISR execution.

    The other parts of codes aside, I included 4 AD conversions in the code just as the case in example projects. However I tried to test the time spent for AD conversion an it took probably 10-30us, which seems a bit slow to me. Is it because I used the wrong way to trigger the ADCs? I used pwm to trigger them, probably I should use EOC as you mentioned?

    Thanks.

    Jingzhe

  • 30us is much too long! That's 1800 clock cycles, how long it takes to run our entire InstaSPIN-FOC solution from sample to output!

    You need to look at the Clock set-up and triggering for your ADC. Use the controlSUITE example from somethign like the DRV8301 kit or the latest in the HVKIT.

     

  • Hi Chris,

    Just in addition, my math blocks are written as functions, would it possibly be better if I change them into using macros as in some example code?

    Jingzhe

  • macros aren't inherently faster than functions, so that's not your problem. you may have an issue with how you have written your functions, but that's hard for me to comment on.

    if you are more comfortable with functions you may want to look at MotorWare.

  • Hi Jingzhe,

    i am sure you did, but just to be sure: do you use IQMath for your calculations? In IQMath, there are some functions that i always try to avoid. For example _IQdiv function. It takes about 63 cycles to calculate. The same with IQNsqrt...

    Maybe there is some potential to speed up your code execution. You can find the times in IQmath_Quickstart.pdf on page 31.

  • Hi Felix,

    Yes I use iqmath to perform my arithmetic as expected. In fact I used quite a number of IQdiv in the block I programmed myself. So do you think it's better to change all the IQdiv into IQmpy if I wish to do division?

    Thanks,

    Jingzhe

  • IQmpy needs much less cycles for calculation. So if you have the possibility to switch from IQdiv to IQmpy you should do that. I had the same problem and solved it the same way.

  • Hi Jingzhe,

    Some useful tips for coding ISRs:

    1. As much as possible keep them short and simple. No complex math. 

    2. Avoid using any loops (for, while etc.. ) inside ISR. For eg. results from 16 ADC channels can be read by individual read instead of using while/for loops.

    3. Do not call functions inside ISRs. Its always better to write the whole code straightaway inside the ISR itself.

    4. Don't do any polling inside ISR. Trigger conversions beforehand if possible and use ADC interrupts for performing control operations.

    5. Run ISRs from SARAM for faster execution. You will see decent performance improvement.

    6. ISRs are best written in assembly. (Thought this is not always possible.)

    Thanks,

    Vivek

  • Hi Vivek,

    I think loading ISR to RAM will be a good idea. What I did is to put the following line at the beginning of main code.

    #pragma CODE_SECTION(MainISR, "ramfuncs");

    Then I call the functions

    MemCopy(&RamfuncsLoadStart, &RamfuncsLoadEnd, &RamfuncsRunStart);

    InitFlash();

    However when I try to run the code, the debugger always go to Illegal_ISR and I don't know why.

    ramfuns is defined in linker command file.

    ramfuncs            :

     LOAD = FLASHA,                         

    RUN = PRAML0,                         

    LOAD_START(_RamfuncsLoadStart),                         

    LOAD_END(_RamfuncsLoadEnd),                         

     RUN_START(_RamfuncsRunStart),                         

    PAGE = 0

    I tried to allocate more space to PRAML0 but the problem still exists.

    Do you have any idea about this?

    Thank you.

    Jingzhe

     

  • Hi Vivek,

    I solved the problem. The InitFlash function was not successfully compiled. I did again and it works now.

    Jingzhe

  • Hi Chris,

    I managed to load ISR to ram and the interrupt can reach 50kHz now.

    Jingzhe

  • That's great!  BTW - with the flash properly intitalized you should only see a small performance hit if running the ISR from flash, but if you have space RAM is always preferred.

     

  • Hi Jingzhe!

    I'm glad to your success. Thus I have given you a good idea from the start. And it's great that it works. But in your post you have mentioned "MemCopy" function (it seems one has name "memcpy").

    Regards,

    Igor

  • Hi Igor,

    Thank you very much for your assistance an good idea. I read the file you gave me. I think MemCopy is a function defined in project-DevInit_F2802x.c and memcpy is one of the basic functions provided in C language header files. Anyway they should do the same job, moving a memory to another place.

    Jingzhe

  • Hi Jingzhe!

    I see. You are right. Indeed there are two versions in controlSUITE: in "development_kits"(MemCopy version) & in "device_support"(memcpy version) folders.

    Regards,

    Igor