CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

"math.h" & interrupts questions SOLVED

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
gjs_rsdi



Joined: 06 Feb 2006
Posts: 468
Location: Bali

View user's profile Send private message Send e-mail

"math.h" & interrupts questions SOLVED
PostPosted: Thu Jun 30, 2016 10:33 pm     Reply with quote

CCS PCH C Compiler, Version 5.059
MPLAB v8.92
PIC18F26K22 at 64MHz

I am trying to figure out 2 things:
1. Using the MPLAB simulator to check math operation time with two int32, I am getting the same time with #include "math.h" and without. I was assuming that the math.h supposed to shorten the calculation time. It will be the same in the real life operation? I mean no difference?
2. If an interrupt will occur in the middle of the math calculation it will be served immediately or just after the calculation.
It will be the same with #include "math.h" and without?
I can't afford delays of 70us+ in the program

Best wishes
Joe


Last edited by gjs_rsdi on Sat Jul 02, 2016 12:30 am; edited 1 time in total
Ttelmah



Joined: 11 Mar 2010
Posts: 19359

View user's profile Send private message

PostPosted: Thu Jun 30, 2016 11:37 pm     Reply with quote

math.h, has nothing whatever to do with the core mathematics.
It provides higher level maths functions, and some defines. Things like PI, sine, cos, exp, log etc..
It only provides the functions contained in it. If your maths works without math.h, then you are not using it's functions.
The math operations take how long they take. The core functions are based on a design done by MicroChip to be as fast as possible in the hardware. Even assembler, basically won't improve them. You can generate your own faster functions by limiting them in some way (for instance, I have done int24 functions in the past to be faster than the int32 arithmetic, when I didn't need the numeric range offered by int32). However if you need int32, you won't improve much if at all. An int32 multiply, will not take '70us+'. On your chip at your clock rate, an int32 multiply will only take about 13.9uSec. If your code is taking 70uSec+, then it is doing a lot more than an int32 multiply, or your chip is not running at the speed you think. Check carefully that your syntax is not actually involving a division (70uSec is almost exactly the time needed for an int32 division on your chip).

The response time, is completely down to you. If your code uses an int32 multiply inside the interrupt, then as standard, you will get the compiler warning "interrupts disabled to prevent reentrancy", and the external arithmetic will finish before the interrupt is called. If you don't use such arithmetic, the interrupt will be serviced immediately. If you must use such arithmetic in your interrupt, then a search here will show how to load a second copy of the core maths library, so that this doesn't happen.

<http://www.ccsinfo.com/forum/viewtopic.php?t=25464&start=4>

Updated:

You do realise you have to tell the simulator your clock rate?.
It does not know how fast the real chip will clock. You need to set the rate via 'Debugger', 'Settings', before any time measurement is meaningful. By default it will be selecting 20MHz, so things would take 3.2* their 'real' time, when measured in the simulator.
gjs_rsdi



Joined: 06 Feb 2006
Posts: 468
Location: Bali

View user's profile Send private message Send e-mail

PostPosted: Fri Jul 01, 2016 2:39 am     Reply with quote

Thanks for the answer Ttelmah

1.
"math.h" usage clear now
The MPLAB watch is set to 64MHz so is correct.
2.
Quote:
An int32 multiply, will not take '70us+'. On your chip at your clock rate, an int32 multiply will only take about 13.9uSec. If your code is taking 70uSec+, then it is doing a lot more than an int32 multiply

You are right. it was a division of int32 by int32 then multiplication by a number of less than 255. Taken apart, it was much less time than 75us, in the range you have written.
As I don't need the high resolution, I find the way to make divisions and multiplications by numbers like 2, 4, 8,...128.
It takes less than 1us.
3.
Regarding interrupts
The calculations are not inside the isr. In the isr I am making a flag=1.
My question is if during a math calculation an interrupt will occur the interrupt will be served immediately and then back to the calculations or it will wait until the calculation is done before serving the interrupt ?

Thank you again for the answer Smile
Best wishes
Joe
RF_Developer



Joined: 07 Feb 2011
Posts: 839

View user's profile Send private message

PostPosted: Fri Jul 01, 2016 4:55 am     Reply with quote

Quote:
My question is if during a math calculation an interrupt will occur the interrupt will be served immediately and then back to the calculations or it will wait until the calculation is done before serving the interrupt.


Maths calculations are nothing special, they are just sequences of perfectly normal instructions. Unless the calculation is coded as a critical section, i.e. it runs with interrupts disabled, and there's no reason it would be unless the same operation is in interrupt code as well as main code, in which case the complier does it for you, warning that "interrupts have been disabled to prevent recursion", or something similar, then the interrupt will be serviced as normal, interrupting the calculation. The calculation will then be continued from where it left off after the interrupt has been serviced.

Be careful to avoid changing non-byte variables in an ISR that may be being used in calculations, or other main/non-isr code. The problem is that access to anything larger than a byte takes more than one instruction, i.e. is non-atomic. If multi-byte variables, whether floats, int16s or whatever, are changed in an ISR they may change as main code is using it. There are a number of techniques that can be used to get round this, making the main code access a critical region is one, and there are other "locking" techniques that can be used, but they all rely on critical sections as their underlying mechanism. Another popular one is to read the variable twice, or until two successive reads are the same. That's not guaranteed to be 100% reliable, at least in theory, as it could just about conceivably be corrupted in the same way twice in succession, but it's more than good enough in practice.

The keyword "volatile" is often used as a hint to compilers that variables can change at any time, but it is generally used to force repeated accesses to what the compiler thinks is loop-invariant code, thus preventing the access from being optimised away. Volatile is not, apparently, used by the CCS compiler to ensure atomic access to variables.
gjs_rsdi



Joined: 06 Feb 2006
Posts: 468
Location: Bali

View user's profile Send private message Send e-mail

PostPosted: Fri Jul 01, 2016 6:59 am     Reply with quote

Thank you RF_Developer

I understand your explanation regarding the interrupt and math issue.
I am trying to keep the maths as simple as possible and most of the times not combining more than one operation in one instruction.
Sometimes I need some division that takes longer, this was the reason of my question, but now is clear.

Best wishes
Joe
Ttelmah



Joined: 11 Mar 2010
Posts: 19359

View user's profile Send private message

PostPosted: Sat Jul 02, 2016 12:56 am     Reply with quote

I did say that the interrupt "would be serviced immediately" (if you weren't using maths in the interrupt handler and therefore triggering the compiler to disable interrupts).

The compiler is smart, and knows if you use binary divisions, that it can substitute rotations, and even byte shifts. Smile

There are some places where if (for instance) you are using fixed multiples, you can improve even further. For instance, in one of the examples, there is a *10, coded as the number being multiplied by 2, then added to itself *4.
So:
Code:

#define timesten(x) x*=2; x+=x*4


So you get x*2 + x*8. Much more efficiently than any 'general' multiplication. Tricks like this are an area, where a bit of thought can make a huge difference to the overall code speed.

You might also want to look at ex_glint.c. This gives an example of how to reduce interrupt response times. Key is that CCS by default saves every register. However if you are doing small things and want fast responses, then you can sit down, look through the assembler generated by the routine you are using in the interrupt, and work out what registers it changes. Then add saving these to the part "Save anything else your code may change", saving nothing else, so you get a handler that is as fast as in assembler.

Have fun. Smile
gjs_rsdi



Joined: 06 Feb 2006
Posts: 468
Location: Bali

View user's profile Send private message Send e-mail

PostPosted: Mon Jul 04, 2016 1:10 am     Reply with quote

Thank you Ttelmah

Started to go through the software to change all the divide by not /2; /4 and so on and also to use *2; *4 etc.
I will check ex_glint.c. I worked for year in assembler, not in the last 10 years, but yeas, will be fun Smile

Best wishes
Joe
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group