View previous topic :: View next topic |
Author |
Message |
autoguider
Joined: 24 Sep 2007 Posts: 82 Location: Aachen
|
Posted: Tue Sep 25, 2018 2:54 pm Post subject: Program seems to reboot itself |
|
|
Dear All,
I found the strange behaviour in my program that I experience the first time.
The µC is a AVR 168 @ 6.144 MHz running on a Pollin evaluation board. External power supply.
Rectifier is on board of the evaluation board.
PC6 is configured as RESET. As far as I can see there is no pull up resistor on the evaluaion board for PC6
Here a short schematic of the program
Definitions & declarations like dim, config ...
Goto main
code of subroutines
sub 1
sub 2
sub init()
sub evaluate_strings()
.
.
main:
call init
do
call evaluates_strings
call Evaluate keys
.
.
loop
Code ISR_1
Code ISR_2
ISR are serving events stimulated by timer0 and timer2.
The subroutines mainly send messages via RS232 as anwers to the evaluation of the input string.
Input and output are buffered.
From time to time after going through as short anwering routine the init procedure gets started. I get it indicated by a message via UART.
That drives me to the conlusion that the AVR is rebooting unexpectedly.
I am running a main timer that produces a cycle with 20 ms period. This timer calculates the on times and the off times for two RC servos.
Execution takes 69 cycles = 11 µs
The timer producing the signals for the 2 servos is called 4 times within the 20 ms frame. 1 execution takes 45 cycles. = 7µs
Is there an event that may cause the controller to rebboot. Overflow ?, Timeouts ?
The reboot happens irregular but alwas after requesting an anwers to an input string.
Please let me have your advice.
best regards
Christian
(BASCOM-AVR version : 2.0.8.1 ) |
|
Back to top |
|
|
i.dobson
Joined: 05 Jan 2006 Posts: 1570 Location: Basel, Switzerland
|
Posted: Tue Sep 25, 2018 3:24 pm Post subject: |
|
|
Hi,
How large are your stacks (SW,HW,FRAME)?
Regards
Ian Dobson _________________ Walking on water and writing software to specification is easy if they're frozen. |
|
Back to top |
|
|
autoguider
Joined: 24 Sep 2007 Posts: 82 Location: Aachen
|
Posted: Tue Sep 25, 2018 5:32 pm Post subject: |
|
|
Hi Ian,
here the data;
$lib "mcs.lbx"
$regfile = "m168def.dat"
$prog &HFF , &HE7 , &HDF , &HF8 ' generated. Take care that the chip supports all fuse bytes.
$crystal = 6144000 ' used crystal frequency 0 error in UART
$baud = 19200 ' used baud rate
$hwstack = 64 ' default use 32 for the hardware stack
$swstack = 20 ' default use 10 for the SW stack
$framesize = 64
Here the usage of the stack for a ISR
push r15 'r 15 to Stack
in r15,sreg 'Read Statusregister R15
push r15 'Statusregister to Stack
push r20 'r 20 to Stack
push r19 'r 19 to Stack
push r28 'Y Register
push r29
push r30 'Z- Register
push r31
ISR should not be nested. To my information the interrupt that is just about to be executed blocks the execution of other interrupts.
In the evaluate_strings subroutine the subroutines to answer re addressed via call subroutine.
There are no parameters that are transferrred to the subroutines. Basically it is like using global variables only.
best regards
Christian |
|
Back to top |
|
|
i.dobson
Joined: 05 Jan 2006 Posts: 1570 Location: Basel, Switzerland
|
Posted: Tue Sep 25, 2018 6:25 pm Post subject: |
|
|
Hi,
What happens if you use pushall/popall in your ISR. If that works then you'll Need to look at the ISR more closely.
On AVR's Interrupts are not nested (when an ISR is active it won't be interrupted by a new Interrupt, unless you Play with asm cli,sei).
You you post all the code, rather than just Little bits.
Regards
Ian Dobson _________________ Walking on water and writing software to specification is easy if they're frozen. |
|
Back to top |
|
|
hgrueneis
Joined: 04 Apr 2009 Posts: 902 Location: A-4786 Brunnenthal
|
Posted: Wed Sep 26, 2018 7:07 am Post subject: |
|
|
Install a 10K pullup on PC6 and increase the stack.
Regards
Hubert |
|
Back to top |
|
|
autoguider
Joined: 24 Sep 2007 Posts: 82 Location: Aachen
|
Posted: Thu Sep 27, 2018 10:00 pm Post subject: Program seems to reboot itself |
|
|
Dear All,
thanks for replying.
I installed the pull-up resistor on the evaluation board. It will definetely help to have clear conditions on the board.
In the meantime i did some research and found that one of my ISRs causes the trouble.
To my opinion it has someting to do with the handling of portC. C6 is tzhe reset !
here some excerpt code of the old ISR that causes trouble: Code: |
Servopuls_isr_t2: 'Creates pulses for the servos
$asm
push r20 'Statusregister in r 30
in r20,sreg 'Statusregister to Stack
push r20 'Servonr
push r19 'adressieren der Ausgänge, allg variable
in r19,portC 'Load status from PortC; C.1 and C.2 are for the servos
AndI r19, &b11111001 'Mask to reset all servo pins
ori r19, &b01000000
!Out Portc , R19 'Set servo outputs to 0
Loadadr B_servonr , X
Ld r20 , X 'ServoNr in r20; Start Value =0
inc r20 'Increment servoNr
cpi r20,1 'Equal to 1 ?
brne Rest1 'if not fill rest of period
' ServoNr =1 1st "on" time
st X , R20 'store incremented B_ServoNr
in r19,portc 'Load status of PortC
OrI r19, &b00000010 'Set C.1 to 1
AndI r19,&b11111011 'update
!Out Portc , R19 'Set pins of PortC
SBI portc,1
Loadadr B_impulsdauer(3) , X 'Load duration of switch on phase
ld r19,x
!Out Ocr2a , R19 'Set value for next ocr2a interrupt
ldi r19,0
!out tccr2, r19 'Set counter value of timer to 0
jmp Endeasm |
I have the strong assumption that the acces to port C causes a reset. The init procedure was statred again and again.
Could you confirm that for some reason Port c.6 can be brought to 0 and then causes a reset ß
Now the "new " code with comments in English language.
Code: |
Servopuls_isr_t2: 'Creates pulses for the servos
$asm
push r20 'save content r20 to stack
in r20,sreg 'load statusregister in r 20
push r20 'save status register to stack
push r19 'save content r19 to stack
cbi portc,1 'Clear C1 = Pulse Servo 1 =0
cbi Portc,2 'Clear C1 = Pulse Servo 2 =0
Loadadr B_servonr , X
Ld r20 , X 'ServoNr in r20; Start Value =2
inc r20 'Increment B_servoNr
'--------------- "ON" time servo 1
cpi r20,3 'Equal to 1 ?
brne OFF_time_servo_1 'if value =4
st X , R20 'store incremented B_ServoNr
SBI portc,1 'set pin c1 =1. "ON" time servo 1
Loadadr B_impulsdauer(3) , X 'Load duration of switch "on" phase
ld r19,x
!Out Ocr2a , R19 'Set value for next ocr2a interrupt
ldi r19,0
!out tccr2, r19 'Set counter value of timer2 to 0
jmp End_ISR_t2 'JMP to exit procedure ISR
'---------------- OFF time servo 1
Off_time_servo_1: 'Fill time gap so that servos get their signals in the 20ms frame
cpi r20,4 'check if value =4
brne ON_Time_Servo_2 'Goto "HIGH" phase servo 2
st x , r20 'store value 4 to B_servonr
Loadadr B_impulsdauer(4) , X 'load value for filling remaining time gap
ld r19,x
!Out Ocr2a , R19
ldi r19,0
!out tccr2, r19 'Set counter value of timer2 to 0
jmp End_ISR_t2
On_time_servo_2:
cpi r20,5 'Check if value =5
brne OFF_time_servo_2 'Goto OFF time servo 2
'--------------- "ON" time servo 2
st x , r20 'store value 5 to B_servonr
sbi portc,2 'set pin c1 =2. "ON" time servo 2
Loadadr B_impulsdauer(5) , X 'Load duration of switch "on" phase servo 2
ld r19,x
!Out Ocr2a , R19 'Set value for "ON" time servo 2
ldi r19,0
out tccr2, r19 'Set counter value of timer to 0
jmp End_ISR_t2 'JMP to exit procedure ISR
Off_time_servo_2:
cpi r20,6 'Check if value =6
brne Reset_Servo_Count 'jmp if b_servonr has normally value 7
st x , r20 ' B_Bervonr = 6; Save value
Loadadr B_impulsdauer(6) , X 'Fetch value for "OFF" time servo 2
ld r19,x 'load value for "OFF" time servo 2 to r19
!Out Ocr2a , R19 'Set timer register to OFF time value
ldi r19,0
!out tccr2, r19 'Set counter value of timer2 to 0
jmp End_ISR_t2 'JMP to exit procedure ISR
Reset_servo_count:
Loadadr B_servonr , X
ldi r20,2
st x ,r20 'Set B_Servonr to 2; Is prepared for the next cycle of this ISR
ldi r19, 0
!Out Tccr2b , R19 'Timer2 is stopped
!out tcnt2 , r19 'Timer 2 counter register =0
End_isr_t2:
pop r19
pop r20 'X Register High to Stack
!out sreg,r20
pop r20
$end Asm
Return
|
Here the code of the timer ISR that takes care of the 20ms frame
Code: | 20ms_Timer0_isr: 'Starts 20ms frame
$asm
push r15 'r 15 to Stack
in r15,sreg 'Read Statusregister R15
push r15 'Statusregister to Stack
push r20 'r 20 to Stack
push r19 'r 19 to Stack
push r28 'Y Register
push r29
push r30 'Z- Register
push r31
Loadadr B_impulsdauer(3) , Z 'Duration of "ON" phase addressed via Z register
ld r20,z 'Duration in r20
Loadadr B_fahrzustand(2) , Y 'Y adresses mode of movement
ld r19 ,y 'value in r19
ADD r20,r19 'Addition, result in r20
st z,r20 'save in Impulsdauer(3)
ldi r19,254 'Calculate time gap to meet 20ms frame servo 1
!Sub R19 , R20
st z+1,r19 'Save in Impulsdauer(4)
ld r19,y+1 'R 19 contains Fahrzustand(3)
ld r20,z+2 'R 20 contains Impulsdauer(5) = ON time servo 2
add r20,r19 'Addition Ergebnis in R20
st z+2,r20 'store new value of "ON" time servo 2 in Impulsdauer(5)
ldi r19,254 Calculate new value for "OFF" time servo 2
!SUB R19 , R20
st z+3,r19
' Noadd:
' Loadadr B_anfangsdelay,z
' ld r20,z
' inc r20
' st z,r20
ldi r20,3 'R20 nun als allg Variable nutzen
!Out Ocr2a , R20 'Set OCR2A to 3 to have a time distance between ISRs
ldi r20,0
!out tcnt2,r20 'Set Counter register to 0 setzen
ldi r20,&B00000011 'Configuration Timer 2 with pre scale etc..
Out Tccr2b , R20 'Load Timer2 register Starts Timer 2
'LDI Ocr2a,1 'Schwellwert auf 2 gesetzt damit ISR schnell ausgelöst wird
'LDI Tcnt2, 0 'Counter 2 auf 0 gesetzt
'LDI Tccr2b, &B00000011
Pop r31 'Stack aufräumen
Pop r30
Pop r29
Pop r28
Pop r19
Pop r20
Pop r15
Out Sreg , R15
pop r15
'Executed operations
'B_Impulsdauer(3) = B_Impulsdauer(2) + B_Fahrzustand(2)
'B_Impulsdauer(5) = B_Impulsdauer(3) + B_Fahrzustand(3)
'startet Timer 2
'Dauer ca 11 us , 69 takte
'reti
$end Asm
Return |
It is a bit a tricky game between 2 interrupt service routines.
Let me share my idea how these ISR cooperate:
' The program serves 2 RC servos.
''
' Angular position of the servo is coded by the pulse width of control pulse.
' Working position is reached with pulse width of 2500 µs.
' Initial position is both servos at 0 position. Pulse width 500µs.
' Every 20 ms a 500µs pulse is given to each servo.
' Timer 0 creates the 20 ms frame and calculates the length of each pulse,
' Servo 1 get its pulse at t=0; Servo 2 gets its pulse at t=2500µs
' This means that Timer 0 calculates the ON time of the pulse at also the remaining time (=OFF time) until the next pulse for the second servo.
' In total there are 20000µs/2500µs= 8 servos possible to handle in the 20 ms frame.
' Timer 0 starts Timer 2.
' Timer 2 creates consecutively the pulses for servo 1 and servo 2.
' In the main loop it is watched that the values for the timers stay in the permitted range.
'.
'
' There are 3 kinds of movement for the servos which is coded in following numbers:
' forward = Angle increasing Value:1; standing ' The program serves 2 RC servos.
'
' Definition of Filter 1 = Normalop; Filter 2 = Focussin; Filter 3 = Illumclr
'
' Angular position of the servo is coded by the pulse width of control pulse.
' Working position is reached with pulse width of 2500 µs.
' Initial position is both servos at 0 position. Pulse width 500µs.
' Every 20 ms a 500µs pulse is given to each servo.
' Timer 0 creates the 20 ms frame and calculates the length of each pulse,
' Servo 1 get its pulse at t=0; Servo 2 gets its pulse at t=2500µs
' This means that Timer 0 calculates the uptime of the pulse at also the remaining time until the next pulse for the second servo.
' In total there are 20000µs/2500µs= 8 servos possible to handle in the 20 ms frame.
' Timer 0 starts Timer 2.
' Timer 2 creates consecutively the pulses for servo1 and servo 2.
' In the main loop it is watched that the values for the timers stay in the permitted range.
'.
'
' There are 3 kinds of movement for the servos which is coded in following numbers:
' forward = Angle increasing Value:1; standing value 0; back value FF ( corresponds to -1´ in 2'complement)
' These values are in the array B_Fahrzustand.
'
' ####################### Function Timer 0
' Timer 0 creates the periodic 20 ms frame and calculates the duration of the ON-phase and the OFF phase of the control pulses.
' By adding the value of B_Fahrzustand to the value for the trigger value of the timer event the pulse width gets modified.
' Addition of 0 (=standing) does not change the value and consequently not the pulse width, Angular position is unchanged.
' Addition of von "forward" ( value=1) increases the pulse width.
' Addition of "back" (value = -1) decreases pulse width.
' Values are stored in the array B_Impulsdauer(6) by Timer 0 ISR
' Index 1 not used
' Index 2 not used
' Index 3 Servo 1 "ON"time
' Index 4.Servo 1 "OFF" time
' Index 5 Servo 2 "ON" time
' Index 6.Servo 2 "OFF" time
' "ON" time+"OFF" time add up to appr. 2500µs
' Then Counter register TCNT2 is set to 0 and OCR2A to the value 3 so that the interrupt of Timer 2 is executed with a short delay.
' Counter 2 is started.
'Here I need to test to come closer to the limits.
' Values of the pulse widths is performed every 20 ms. This results in a desired slow movement of the servos.
'.
' ####################### Function Timer 2
' In the Servopuls_ISR (Timer2) both ouputs for the servos will be brought to 0.
' OCR2A is loaded with the uptime value for servo 1. Output is set to 1.ISR is finished.
' When the timer reaches the "ON"ptime value the ISR is started again.
' Both servo outputs are set to 0.
' Then the value for servo 1 "OFF" time is send to OCR2a.. TCNT2 is set to 0. ISR finished.
' When Timer has reached the value of OCR2a the ISR is started again.
' OCR 2a now receives the value for servo 2 uptime. When counter reaches the value of OCR2a the ISR is started again.
' Both output pins are set to 0. OCR2A receives the value for the OFF-time of servo 2.
' Next execution of the ISR stops timer 2. No further pulses are created until timer 0 initiates start of timer 2
I will be testing the new code.
Some good advice is always welcome.
best regards
Christian |
|
Back to top |
|
|
EDC
Joined: 26 Mar 2014 Posts: 971
|
Posted: Fri Sep 28, 2018 6:38 am Post subject: |
|
|
Why dont you save R26 and R27 if your Loadadr loads data into X?
Such short code:
Code: | $regfile = "m168def.dat"
$crystal = 8000000
$hwstack = 64
$swstack = 32
$framesize = 128
Dim B_impulsdauer(3) As Byte
Loadadr B_impulsdauer(3) , X
End |
Is translated into:
Code: | 14: Loadadr B_impulsdauer(3) , X
000000A4: E0A2 LDI R26, $02
000000A6: E0B1 LDI R27, $01 |
So X is blurred for sure because you dont save and restore it (no Push and Pop R26,R27).
You must also know that Buffered Input/Output causes additional interrupts. With buffered output you have Interrupt on every char that must be sent. |
|
Back to top |
|
|
autoguider
Joined: 24 Sep 2007 Posts: 82 Location: Aachen
|
Posted: Fri Sep 28, 2018 11:04 am Post subject: |
|
|
Many thanks for the advice.
I modified the ISR with saving the X register.
I also changed the UART to non buffered in both directions. Communication to the PC via RS232 runs well.
best regards
Christian |
|
Back to top |
|
|
|
|
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 You cannot attach files in this forum You cannot download files in this forum
|
|