|
|
View previous topic :: View next topic |
Author |
Message |
cagabit
Joined: 19 Dec 2014 Posts: 7
|
cant make it work the locate ! |
Posted: Fri Dec 19, 2014 9:11 am |
|
|
Hi to all,
Have a project ongoing and have some timing performance problems. Thought to convert some math functions to ASM to gain some cycles. Not very experienced on ASM.
For pic 18f2550, using v5.015
I want to make a function, and put the asm part in it.
if I am not wrong, the variables must be on the same page, for the asm code to directly get or set them ??! To test this i wrote this small code :
Code: |
int16 dat[6]={10001,10002,10003,10004,10005,10006};
#locate dat=0x50
int16 refA = 20250;
#locate dat=0x5C
int16 refB = 20020;
#locate dat=0x5E
float ktemp[4]={10008,10009,10010,10011};
#locate dat=0x50
|
But from the debug RAM window or the "printf ... &variable" code they are not on the place i set. Compiler is not putting these variables to the address i wrote, something beyond my knowledge is happening here !
Also as far as i get from the posts, i should not save the state of some registers and reload at the end of the function, since there is no interrupt, is it true ? Can i directly get the values and do some math and set the result to the variable from the ASM code ?
Any guidance is appreciated. Thanks. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19498
|
|
Posted: Fri Dec 19, 2014 9:32 am |
|
|
If you access the variables by name in the assembler, CCS will automatically handle the bank switching for you. They can be left in their normal location.
The reason they won't 'locate' is that you are trying to place them in the access RAM, and the compiler uses this already to speed the access to important variables.
What is the actual function you want to recode?. Most of the standard functions are very close to optimal.
Interrupts save and restore registers when they happen.
Look at the example given under #ASM in the manual.
It shows how you access variables by name, and how to return a value from a function. |
|
|
cagabit
Joined: 19 Dec 2014 Posts: 7
|
|
Posted: Fri Dec 19, 2014 10:00 am |
|
|
Thanks, great summary.
Then i can directly test the function. The C code trying to convert is :
Code: |
dat[1]=dat[1] * ktemp[1];
tt= logt[dat[1]];
if(RefA > tt)
dat[1]= ((int32)(RefA-tt)*1000)/RefB ;
else dat[1]=0;
if (dat[1]>1000) dat[1]=1000;
|
All variables 16-bit except ktemp[] is float, it is a coefficient actually.
Logt is logarithm table consisting 1024 elements, i load the result from table to a temporary variable tt, because of some problems. And as far as I can measure this part is taking 108uS with 48Mhz osc. ( Also USB is active to transfer the data to PC ).
I am trying to measure the speed of a liquid which passes 2 lines of led barriers. Get the instant level with A/D and try to calibrate with this code snippet. After this I have to make cross-correlation also to calculate the time lag between 2 signal arrays. Which i will come to that after this.
The test measurements make me suspect that I can not read frequent enough so I am trying to shorten the read & calibrate part.
I thought some gain can be accomplished with converting this to ASM ? What do you think ?
Thanks, |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19498
|
|
Posted: Fri Dec 19, 2014 12:02 pm |
|
|
First thing is that ktemp, being a float, forces float multiplication on the first line. That is about 40uSec of your time straight away.
The rest is almost all the division. Division is foul. costs about 5* as much as multiplication. It'd actually be faster if you stored 1000/RefB as a float, and multiplied by this!. I'd suggest you try simply storing 1000/RefB as a float when it is generated, and in this code just do the one float multiply by this. That ought to save perhaps 30uSec.
Microchip do a carefully optimised assembler maths library, and the times of the CCS routines are within a couple of cycles of the times from this, so you are not going to improve much with the current approach.
Other thing to consider, is scaling.
For instance, if you stored ktemp*256 as an int32, again when it is generated, then you might be able to do the first line as:
Code: |
dat[1]=(dat[1] * ktemptimes)/256;
|
Using int32 arithmetic. The /256, is one of the 'exceptions' to division being horrible, since the compiler can do this using rotation (and will do).
At least another 10uSec saved inside this routine..... |
|
|
cagabit
Joined: 19 Dec 2014 Posts: 7
|
|
Posted: Sat Dec 20, 2014 7:52 am |
|
|
Thank you Ttelmah.
Really got the point, no need for ASM, the DIV and /256 trick will save my day i think. The time gain will be enough i think. |
|
|
|
|
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
|