Hello everyone, I'm an Italian student and I'm working on a MCF52259 demo. I'm trying to control a LED with the MCF52259 and I've written this code following an old work by a student, but the doesn't work at the right frequency, even if I set it manually...
Do you see any error in my code? I can't figure out what's wrong about it. Thank you very much for your aid!!
/*** ### MCF52259CAG80 "Cpu" init code ... ***/
/*** PE initialization code after reset ***/
/* System clock initialization */
/* CCHR: ??=0,??=0,??=0,??=0,??=0,CCHR=5 */
setReg8(CCHR, 0x05); /* Set the predivider */
/* SYNCR: LOLRE=0,MFD=3,LOCRE=0,RFD=0,LOCEN=0,DISCLK=0,FWKUP=0,??=0,??=0,CLKsrc=1,PLLMODE=1,PLLEN=1 */
setReg16(SYNCR, 0x3007); /* Set the SYNCR register */
while (!(SYNSR & SYNSR_LOCK_BITMASK)){} /* Wait until the PLL is locked. */
/* LPDR: ??=0,??=0,??=0,??=0,LPD=0 */
setReg8(LPDR, 0x00); /* Set the low power divider */
/* RTCCR: ??=0,EXTALEN=0,??=0,OSCEN=0,KHZEN=0,REFS=0,LPEN=0,RTCSEL=1 */
setReg8(RTCCR, 0x01); /* Set the RTC oscillator and RTC clock select */
/* BWCR: ??=0,??=0,??=0,??=0,??=0,??=0,BWDSTOP=0,BWDSEL=1 */
setReg32(BWCR, 0x01); /* Set the BWCR register */
/*** End of PE initialization code after reset ***/
my code..
double Out_sigma2=0;
double Out_sigma2_old=0;
double Vout=0;
double Vin=0;
double PidEnable=0;
/* Blocco sigma delta del dimming */
Vin=0.5; // valore fisso per prova
// random2 = rand() ;
// random2=random2/65536;
Out_sigma2=Vin-Vout+Out_sigma2_old;//+random2;
if (Out_sigma2<0.5)
{
Vout=0;
Bit1_PutVal(FALSE);
PidEnable=0;
}
else
{
Vout=1;
Bit1_PutVal(TRUE);
PidEnable=1;
}
Out_sigma2_old=Out_sigma2;
I set the micro so that it should work at 80 MHz, but the output switches at 100kHz!!!!!!
On the contrary, if I execute this code:
Bit1_PutVal(TRUE);
Bit1_PutVal(FALSE);
the exit switches at 3MHz !!!
Help me please!!!
Bit1_PutVal(FALSE); // Setto l'uscita AN5 a o Volt
;
0x0000000C 0x4217 clr.b (a7)
0x0000000E 0x4EB900000000 jsr _Bit1_PutVal
void Bit1_PutVal(bool Val)
; 76: {
;
0x00000000 _Bit1_PutVal:
; Bit1_PutVal:
0x00000000 0x4E560000 link a6,#0
0x00000004 0x102E0008 move.b 8(a6),d0
;
; 77: if (Val) {
;
0x00000008 0x4A00 tst.b d0
0x0000000A 0x670A beq.s *+12 ; 0x00000016
;
; 78: setReg8(SETAN, 0x20); /* SETAN5=0x01 */
;
0x0000000C 0x7020 moveq #32,d0
0x0000000E 0x13C000000000 move.b d0,___IPSBAR+1048634
;
; 79: } else { /* !Val */
;
0x00000014 0x600A bra.s *+12 ; 0x00000020
;
; 80: setReg8(CLRAN, 0xDF); /* CLRAN5=0x00 */
; 81: } /* !Val */
;
0x00000016 0x103C00DF move.b #-33,d0 ; '.'
0x0000001A 0x13C000000000 move.b d0,___IPSBAR+1048658
;
; 82: }
;
0x00000020 0x4E5E unlk a6
0x00000022 0x4E75 rts
I unassembled the code and counted the instructions, they are 8 for "1" output.
I wonder, I need a Dimming part working at 100kHz, a Sigma-Delta working at 800 KHz and an ADC part working at 100kHz with 3 interrupts... should I use a faster micro?
Hi
Try the following code:
setReg8(SETAN, 0x20);
setReg8(CLEARAN, 0x20);
setReg8(SETAN, 0x20);
setReg8(CLEARAN, 0x20);
setReg8(SETAN, 0x20);
setReg8(CLEARAN, 0x20);
setReg8(SETAN, 0x20);
setReg8(CLEARAN, 0x20);
setReg8(SETAN, 0x20);
setReg8(CLEARAN, 0x20);
and see what speed the output changes at.
Note that often port toggling is not as fast as the instruction speed since port accesses can often not be performed at full speed. A speed of 12MHz is considered as good from a processor of this class. The speed achieved is also dependent on SW - the code you are presently testing is not written to optimise speed
The M52259 is a powerful processor and can be used in applications doing a great deal of fast functionaility, but it needs to be used correctly. Some of the functions that you mention are not necessarily suited to being implemented in pure SW - the chip has great peripherals such as DMA timers etc. which will probably allow you to do much of what you want to do without the CPU making any effort of its own.
The trick is in utilising the dormant capabilities of the device in an efficient and intelligent manner. By keeping SW intervention to a minimum and applying HW resources to a maximum you will achieve the best performance for the minimum CPU power overhead. It is always possible to chose a faster (more expensive) processor (or DSP if this is more suited) but to do this due to poor design and not real needs will also result in a poor solution.
Regards
Mark
Hi
If 3MHz is fastest speed that you achieve using straight-line instructions it means that you are hitting the limits imposed by the port writes and not the CPU. I have never tried this on the M52259 so will need to check to make sure of no errors.
The biggest problem with you code which is restricting speed is the fact that the loop is using floating point arithmetic to compare two values. Generally floating point arithmetic is avoided wherever possible since it involves a high overhead and subsequently dramatically slows execution time (excepts being chips designed for this type of operation like high end DSPs).
Usually there is no need to use floating point for such controls since the values collected are generally hexadecimal in nature and are only converted to floating point for human readability.
If you simply scale the values up you will avoid floating point operations and will achieve must faster speeds.
Eg.
fnRoutine(double input)
{
if (input < 0.5) {
}
}
can be replaced by
fnRoutine (unsigned long input)
{
if (input < 0x7fffffff) {
}
}
where the input is represented on a scale from 0 (for 0.000...) to 0xffffffff (for about 1.000000) and 0.5 is (about 0x7ffffffff).
Processors will be able to do this may times faster.
Regards
Mark
Thank you very much for your help; I tried to set all the variables' type to int and now it works as fast as it should.
Now, I'm making a 1st order sigma delta with this code:
int counter = 0;
int Out_sigma2=0;
int Out_sigma2_old=0;
int Vout=0;
int Vin=0;
void TI1_OnInterrupt(void)
{
/* Write your code here ... */
Vin=0; // valore fisso per prova
Out_sigma2=Vin-Vout+Out_sigma2_old;
if (Out_sigma2<0)
{
Vout=-1;
setReg8(MCF_GPIO_CLRAN, 0xDF);
}
else
{
Vout=1;
setReg8(MCF_GPIO_SETAN, 0x20);
}
Out_sigma2_old=Out_sigma2;
}
The problem is that, setting T1-interrupt's frequency to 800khz, I get an output at about 300khz, instead of 400khz, while if I set T1_interrupt's frequency at 600 khz, I get the expected 300 khz in output.
Is it possible that the micro can't handle the interrupts properly if they are too fast??
Hi
With interrupts arriving at a rate of 800kHz each interrupt has just 1.25us to be handled. This limits the code that can run during this time to maybe 100 typical instructions if you are lucky, but heavily depending oin the instruction types.
Usually a timer is used to generate such outputs and not SW code, but you will need to see whether there is a timer in the device that is suitable to doing this (check DMA timer and PWM capabilities).
If there is no way around making the decision in SW DSPs are typically used since they are optimised for such functions.
Regards
Mark
Hi
Please step through your code in the debugger in "assembler view" and count the instructions between the instructions where the outputs are set to '1' and '0'.
Assuming that each instruction takes two clocks (25ns, which is not true since they vary from 1 to 4 in most cases but sometime a lot more), plus execution from FLASH will be a little slower, see whether you can see whether the speed of the outputs is as expected or not.
regards
Mark