| 
	
	|  |  |  
	
		| View previous topic :: View next topic |  
		| Author | Message |  
		| mbge5amw 
 
 
 Joined: 13 Dec 2004
 Posts: 15
 Location: Yorkshire, UK
 
 
			      
 
 | 
			
				| variables being overwritten - 2.236 - PIC18F258 - can bus |  
				|  Posted: Tue Feb 20, 2007 7:56 am |   |  
				| 
 |  
				| I have tried to recreate this in a smaller project but have been unable, I have therefore picked out what I think may be the relevant parts of this project to see if anyone can see what is going wrong. 
 99% of the time it is running fine, however I appear to be getting memory corruption.
 I have found talk on the message board of problems with certain compilers overwriting data with the can bus routines but I am using 2.236 which sounds to be the most stable.
 
 I have a motor control project which basically goes like this.
 Incoming data on CAN bus is buffered in interrupt routine.
 Main loop then decodes this data to work out required motor speed, using motor_convert_100_12 amongst other routines.
 Timer generates interrupts at varying rate to cause next step to be written to stepper motor.
 Also when a sensor is triggered the current position is stored in memory ready for the main loop to check that the motor is where it is expected to be.
 
 The memory that gets corrupted is the first 2 elements of the array motor_fast_step_size_lookup[] i.e. addresses 02A and 02B
 The value of 02B after corruption just happens to be the variable passed to motor_convert_100_12() and this routine uses addresses 22A and 22B for data manipulation.
 
 I have confirmed that I am not writing values to the array motor_fast_step_size_lookup[] through errant code - this is normally written once on power up and then referred to from then on.
 
 I imagine that for some reason the bank address for data writing is getting corrupted and changed from 2 to 0, but I cannot see why.
 Am I right in thinking that the compiler should handle all this, I am a bit stuck now to see what I can do.
 
 If you wish to see any other aspects of the files I can provide the relevant info.
 
 Thanks in advance for your help.
 
 Andy
 
 
  	  | Code: |  	  | 
 begin P3M00.C
 
 #include "18F258.h"
 #device *=16
 
 #DEVICE ADC=8   // 8 bit resolution is enough for our purposes, and maintains compatability with other devices as well as using less memory
 
 #define CLOCK_USED_MHZ 20
 #define CLOCK_USED 20000000
 
 #use delay(clock=CLOCK_USED, restart_wdt)
 #use rs232 (baud=57600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
 #use i2c (master, sda=PIN_C4, scl=PIN_C3, FORCE_HW)
 #define _I2C_W_ADDRESS_ 0x5A
 
 #fuses HS, WDT,NODEBUG,NOLVP,PUT
 
 
 /**********************************************************/
 /*       Name: motor_datum_isr
 /*    Purpose: store details of speed travelling at when sensor passed and abs pos read at the time
 /*             this will be decoded when the processor has time and abs pos modified if needbe
 /* Design status: incomplete
 // amw - just need to verify if force_stop is needed on preset control, may stop us reaching presets above vertical
 /**********************************************************/
 #int_ext
 void motor_datum_isr (void)
 {
 if (motor_datum_retrigger_step_size == 0)               // if already have data to decode then decode that,
 {                                                       // don't read any new data
 motor_datum_retrigger_pos = motor_act_step_pos;
 motor_datum_retrigger_microstep = motor_micro_step_pos;
 motor_datum_retrigger_timer_reload = motor_timer_actual_period;
 motor_datum_retrigger_step_size = motor_actual_step_size;
 motor_datum_retrigger_direction = motor_actual_direction;
 motor_datum_retrigger_prescaler = motor_actual_prescale;
 motor_datum_retrigger_postscaler = motor_actual_postscale;
 }
 
 if (frame_axis == TILT)
 {
 if (motor_finding_upper_limit == FALSE)               // if we are not deliberately trying to reach limit
 if (motor_actual_direction < 0)                     // and moving upwards
 motor_force_stop = TRUE;
 }
 }
 
 /**********************************************************/
 /*       Name: motor_timer_isr
 /*    Purpose: call external routines to reload timer and write step
 /* Design status: appears complete - untested
 /**********************************************************/
 #ifndef _NO_REAL_STEPS_                                   //
 #int_timer1                                               //
 #endif
 void motor_timer_isr (void)                               //
 {                                                         //
 static signed int8 postscale_counter = 0;               //
 int16 local_timer_reload;                               //
 
 local_timer_reload = (0xFFFF - motor_timer_actual_period);
 
 set_timer1 (local_timer_reload);                        // set timer ready for next step
 
 
 <snip> (lengthy series of branches and calcultaions to move motor by required amount and calculate required delay before calling timer again)
 
 
 if (get_timer1 () < (local_timer_reload))             // if ISR latency was so long it missed a trigger
 {                                                     //
 set_timer1 (0xFC00);                                // so try again ASAP (with a little time left to process program loop stuff and decode comms)
 }                                                     //
 }                                                       //
 }                                                         //
 
 
 
 /**********************************************************/
 /*       Name: motor_convert_100_12
 /*    Purpose: take a number in the range -100 to +100 and convert it into range -12 to +12
 /* Design status: corrupts data at 02A and 02B courteousy of scratch data at 22A perhaps?
 /**********************************************************/
 signed int8 motor_convert_100_12 (signed int8 input_speed)
 {
 signed int8 local_speed;
 
 local_speed = input_speed;
 
 if (local_speed > 100)
 local_speed = 100;
 if (local_speed < -100)
 local_speed = -100;
 
 return (int8) ( local_speed * 12L / 100);         // convert from full scale into -12 > +12
 }
 
 end P3M00.C
 
 | 
 
  	  | Code: |  	  | 
 begin OUTPUT
 
 Executing: "C:\Program Files\PICC\PICC PCH 3_236\Ccsc.exe" "P3M00.C" +FH +DF +LN +T -A +M +Z +Y=9 +EA
 
 >> Warning 216 "E:\work\p3m00\P3M00.C" Line 150(0,1): Interrupts disabled during call to prevent re-entrancy:  (@DIV88)
 >> Warning 216 "E:\work\p3m00\P3M00.C" Line 150(0,1): Interrupts disabled during call to prevent re-entrancy:  (@MUL1616)
 >> Warning 202 "E:\work\p3m00\device.h" Line 16(7,10): Variable never used:   rs232_errors
 Memory usage:   ROM=93%      RAM=33% - 50%
 0 Errors,  3 Warnings.
 
 end OUTPUT
 
 | 
 
  	  | Code: |  	  | 
 begin P3M00.SYM
 
 000     @SCRATCH
 001     @SCRATCH
 001     _RETURN_
 002     @SCRATCH
 003     @SCRATCH
 004     @SCRATCH
 005     @INTERRUPT_AREA
 006     @INTERRUPT_AREA
 007     @INTERRUPT_AREA
 008     @INTERRUPT_AREA
 009     @INTERRUPT_AREA
 00A     @INTERRUPT_AREA
 00B     @INTERRUPT_AREA
 00C     @INTERRUPT_AREA
 00D     @INTERRUPT_AREA
 00E     @INTERRUPT_AREA
 00F     @INTERRUPT_AREA
 010     @INTERRUPT_AREA
 011     @INTERRUPT_AREA
 012     @INTERRUPT_AREA
 013     @INTERRUPT_AREA
 014     @INTERRUPT_AREA
 015     @INTERRUPT_AREA
 016     @INTERRUPT_AREA
 017     @INTERRUPT_AREA
 018     @INTERRUPT_AREA
 019     rs232_errors
 01A     motor_force_stop
 01B     motor_report_locate_complete
 01C     motor_repeat_locate
 01D     motor_select_next_function_flag
 01E     motor_update_current_flag
 01F     motor_unattainable_step_flag
 020     motor_finding_upper_limit
 021     motor_force_pfd
 022     motor_modify_current_flag
 023     motor_current_level
 024-029 motor_slow_step_size_lookup
 02A-02F motor_fast_step_size_lookup
 
 <snip>
 
 229     motor_config.@SCRATCH
 22A     motor_convert_100_12.local_speed
 22A     motor_config_8.memory_location
 22A     motor_config_16.memory_location
 22A     motor_calibrate_if_required.@SCRATCH
 22A     motor_report_boot_up.@SCRATCH
 22A     motor_config.@SCRATCH
 22B-22C motor_config_16.required_value
 22B-22C motor_process_datum.expected_pos
 22B-22C motor_config_8.required_value
 22B     motor_convert_100_12.@SCRATCH
 22B     motor_config.@SCRATCH
 22C     motor_convert_100_12.@SCRATCH
 22C     motor_config.@SCRATCH
 
 <snip>
 
 Compiler Settings:
 Processor:      PIC18F258
 Pointer Size:   16
 ADC Range:      0-255
 Opt Level:      9
 Short,Int,Long: 1,8,16
 
 <snip>
 
 
 end P3M00.SYM
 
 | 
 
  	  | Code: |  	  | begin P3M00.LST
 
 CCS PCH C Compiler, Version 3.236, 31524               20-Feb-07 13:04
 
 Filename: P3M00.LST
 
 ROM used: 30576 bytes (93%)
 Largest free fragment is 2192
 RAM used: 512 (33%) at main() level
 773 (50%) worst case
 Stack:    21 worst case (17 in main + 4 for interrupts)
 
 <snip>
 
 .................... /**********************************************************/
 .................... /*       Name: motor_datum_isr
 .................... /*    Purpose: store details of speed travelling at when sensor passed and abs pos read at the time
 .................... /*             this will be decoded when the processor has time and abs pos modified if needbe
 .................... /* Design status: incomplete
 .................... // amw - just need to verify if force_stop is needed on preset control, may stop us reaching presets above vertical
 .................... /**********************************************************/
 .................... #int_ext
 .................... void motor_datum_isr (void)
 .................... {
 ....................   if (motor_datum_retrigger_step_size == 0)               // if already have data to decode then decode that,
 *
 0BDC:  MOVLB  1
 0BDE:  MOVF   x23,F
 0BE0:  BNZ   0C06
 ....................   {                                                       // don't read any new data
 ....................     motor_datum_retrigger_pos = motor_act_step_pos;
 0BE2:  MOVFF  155,120
 0BE6:  MOVFF  154,11F
 ....................     motor_datum_retrigger_microstep = motor_micro_step_pos;
 0BEA:  MOVFF  156,127
 ....................     motor_datum_retrigger_timer_reload = motor_timer_actual_period;
 0BEE:  MOVFF  131,122
 0BF2:  MOVFF  130,121
 ....................     motor_datum_retrigger_step_size = motor_actual_step_size;
 0BF6:  MOVFF  143,123
 ....................     motor_datum_retrigger_direction = motor_actual_direction;
 0BFA:  MOVFF  149,124
 ....................     motor_datum_retrigger_prescaler = motor_actual_prescale;
 0BFE:  MOVFF  145,125
 ....................     motor_datum_retrigger_postscaler = motor_actual_postscale;
 0C02:  MOVFF  147,126
 ....................   }
 ....................
 ....................   if (frame_axis == TILT)
 0C06:  MOVF   x5D,W
 0C08:  SUBLW  02
 0C0A:  BNZ   0C1A
 ....................   {
 ....................     if (motor_finding_upper_limit == FALSE)               // if we are not deliberately trying to reach limit
 0C0C:  MOVF   20,F
 0C0E:  BNZ   0C1A
 ....................       if (motor_actual_direction < 0)                     // and moving upwards
 0C10:  BTFSC  x49.7
 0C12:  BRA    0C16
 0C14:  BRA    0C1A
 ....................         motor_force_stop = TRUE;
 0C16:  MOVLW  01
 0C18:  MOVWF  1A
 ....................   }
 .................... }
 
 <snip>
 
 .................... /**********************************************************/
 .................... /*       Name: motor_timer_isr
 .................... /*    Purpose: call external routines to reload timer and write step
 .................... /* Design status: appears complete - untested
 .................... /**********************************************************/
 .................... #ifndef _NO_REAL_STEPS_                                   //
 0C1A:  BCF    FF2.1
 0C1C:  MOVLB  0
 0C1E:  GOTO   008A
 .................... #int_timer1                                               //
 .................... #endif
 .................... void motor_timer_isr (void)                               //
 .................... {                                                         //
 ....................   static signed int8 postscale_counter = 0;               //
 ....................   int16 local_timer_reload;                               //
 ....................
 ....................   local_timer_reload = (0xFFFF - motor_timer_actual_period);
 *
 1CEE:  MOVLW  FF
 1CF0:  BSF    FD8.0
 1CF2:  MOVLB  1
 1CF4:  SUBFWB x30,W
 1CF6:  MOVLB  2
 1CF8:  MOVWF  xE9
 1CFA:  MOVLW  FF
 1CFC:  MOVLB  1
 1CFE:  SUBFWB x31,W
 1D00:  MOVLB  2
 1D02:  MOVWF  xEA
 ....................
 ....................   set_timer1 (local_timer_reload);                        // set timer ready for next step
 1D04:  MOVFF  2EA,FCF
 1D08:  MOVFF  2E9,FCE
 ....................
 
 
 <snip> (lengthy series of branches and calcultaions to move motor by required amount and calculate required delay before calling timer again)
 
 ....................     if (get_timer1 () < (local_timer_reload))             // if ISR latency was so long it missed a trigger
 2006:  MOVF   FCE,W
 2008:  MOVFF  FCF,03
 200C:  MOVLB  2
 200E:  MOVWF  xEB
 2010:  MOVFF  03,2EC
 2014:  MOVF   xEC,W
 2016:  SUBWF  xEA,W
 2018:  BNC   2028
 201A:  BNZ   2022
 201C:  MOVF   xE9,W
 201E:  SUBWF  xEB,W
 2020:  BC    2028
 ....................     {                                                     //
 ....................       set_timer1 (0xFC00);                                //  try again ASAP (with a little time left to process program loop stuff and decode comms)
 2022:  MOVLW  FC
 2024:  MOVWF  FCF
 2026:  CLRF   FCE
 2028:  MOVLB  1
 ....................     }                                                     //
 ....................   }                                                       //
 .................... }                                                         //
 
 <snip>
 
 .................... /**********************************************************/
 .................... /*       Name: motor_convert_100_12
 .................... /*    Purpose: take a number in the range -100 to +100 and convert it into range -12 to +12
 .................... /* Design status: corrupts data at 02A and 02B courteousy of scratch data at 22A perhaps?
 .................... /**********************************************************/
 .................... signed int8 motor_convert_100_12 (signed int8 input_speed)
 .................... {
 ....................   signed int8 local_speed;
 ....................
 ....................   local_speed = input_speed;
 *
 54DE:  MOVFF  229,22A
 ....................
 ....................   if (local_speed > 100)
 54E2:  MOVLB  2
 54E4:  BTFSC  x2A.7
 54E6:  BRA    54F2
 54E8:  MOVF   x2A,W
 54EA:  SUBLW  64
 54EC:  BC    54F2
 ....................     local_speed = 100;
 54EE:  MOVLW  64
 54F0:  MOVWF  x2A
 ....................   if (local_speed < -100)
 54F2:  MOVF   x2A,W
 54F4:  XORLW  80
 54F6:  SUBLW  1B
 54F8:  BNC   54FE
 ....................     local_speed = -100;
 54FA:  MOVLW  9C
 54FC:  MOVWF  x2A
 ....................
 ....................   return (int8) ( local_speed * 12L / 100);         // convert from full scale into -12 > +12
 54FE:  CLRF   03
 5500:  MOVF   x2A,W
 5502:  MOVWF  00
 5504:  BTFSC  FE8.7
 5506:  DECF   03,F
 5508:  MOVWF  x2B
 550A:  MOVFF  03,22C
 550E:  CLRF   18
 5510:  BTFSC  FF2.7
 5512:  BSF    18.7
 5514:  BCF    FF2.7
 5516:  MOVFF  03,2F2
 551A:  MOVWF  xF1
 551C:  CLRF   xF4
 551E:  MOVLW  0C
 5520:  MOVWF  xF3
 5522:  MOVLB  0
 5524:  CALL   0E3C
 5528:  BTFSC  18.7
 552A:  BSF    FF2.7
 552C:  MOVFF  02,22D
 5530:  MOVFF  01,22C
 5534:  MOVFF  02,22F
 5538:  MOVFF  01,22E
 553C:  MOVLB  2
 553E:  CLRF   x31
 5540:  MOVLW  64
 5542:  MOVWF  x30
 5544:  MOVLB  0
 5546:  BRA    5462
 5548:  MOVF   01,W
 .................... }
 554A:  RETLW  00
 ....................
 
 
 <snip>
 
 Configuration Fuses:
 Word  1: 2200   HS NOOSCSEN
 Word  2: 0F0E   BROWNOUT WDT128 WDT BORV20 PUT
 Word  3: 0000
 Word  4: 0081   STVREN NODEBUG NOLVP
 Word  5: C00F   NOPROTECT NOCPD NOCPB
 Word  6: E00F   NOWRT NOWRTD NOWRTB NOWRTC
 Word  7: 400F   NOEBTR NOEBTRB
 
 end P3M00.LST
 
 
 | 
 |  |  
		|  |  
		| PCM programmer 
 
 
 Joined: 06 Sep 2003
 Posts: 21708
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Tue Feb 20, 2007 11:02 pm |   |  
				| 
 |  
				| You have an array that's getting stepped on.    Your believe that it's caused by some sort of addressing problem.
 
 Here's something to try.   Rename the original array by appending
 "_old" onto the end of it.   Leave it in its present location as a place
 holder.   Then create a new version of the array (with the original
 name) up in an out-of-the-way RAM location, say, up at 0x500.
 Use the #locate directive to do this.   Example:
 
  	  | Quote: |  	  | // Rename the original array to "old".
 int8 motor_fast_step_size_lookup_old[6];
 .
 .
 .
 // Add these two lines at the end of all your existing declarations.
 int8 motor_fast_step_size_lookup[6];
 #locate motor_fast_step_size_lookup = 0x500
 | 
 
 Then see if you still have the same problem.
 |  |  
		|  |  
		| mbge5amw 
 
 
 Joined: 13 Dec 2004
 Posts: 15
 Location: Yorkshire, UK
 
 
			      
 
 | 
			
				|  |  
				|  Posted: Wed Feb 21, 2007 2:37 am |   |  
				| 
 |  
				| I have made that modification exactly as described above and the fault remains affecting the same location, ie   motor_fast_step_size_lookup_old[]  (at 0x002A)is getting overwritten
 but motor_fast_step_size_lookup[]  (at 0x0500) remains intact so far as I can tell.
 
 This seems to be a good fix for now, as my genuine data is uncorrupted, but I remain worried that the cause of this data corruption may also affect another location that I can't spot so easily and thus lead to niggling bugs remaining in the code.
 
 As a crude workaround, is there perhaps a switch that will force the compiler to always specify the memory bank before accessing memory, or to always use 16 bit addressing.  I realise this would probably slow the code down but this may be a necessary sacrifice in order to ensure reliability.
 
 TIA
 
 Andy
 |  |  
		|  |  
		| PCM programmer 
 
 
 Joined: 06 Sep 2003
 Posts: 21708
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Wed Feb 21, 2007 3:16 am |   |  
				| 
 |  
				| I agree that the cause should be found.   The real way to find it would be to use an ICE and trigger it when a memory write occurs to 0x2A.
 Without an ICE it probably has to be done by inspecting the .LST file,
 so a smaller program would make it easier.
 |  |  
		|  |  
		| mbge5amw 
 
 
 Joined: 13 Dec 2004
 Posts: 15
 Location: Yorkshire, UK
 
 
			      
 
 | 
			
				|  |  
				|  Posted: Wed Feb 21, 2007 3:50 am |   |  
				| 
 |  
				| I could take a look at shrinking the code but this precise problem has only come to light in the latest stages of code development, I am concerned that shrinking the code would simply make it go away as I would take away the exact set of triggers. 
 A few ideas I have:
 1. Is the memory bank setting, as set by MOVLB, automatically stored in the stack during interrupts?  Perhaps a stack overflow due to numerous interrupts and deep subroutines?  I'll have a search on the forum to find some more info on this and see what looks relevant to my project.
 EDIT - not this as I already had the STVREN fuse to protect from this
 
 2. ICE: I have an ICD-U40 but using the command line PCM compiler.  Do I need to upgrade to PCWH or do I also need to upgrade the hardware too - as far as I recall the ICD allows you to put break points in code but not conditional breaks.
 
 3. Try very slimline code but keeping all the existing interrupt routines.
 
 4. Check for any hardware errors as described in http://www.ccsinfo.com/forum/viewtopic.php?t=27543&highlight=silicon+bug
 
  	  | Quote: |  	  | Silicon bug in the chip - some 18F series had a problem where they skipped an address when returning from an interrupt. This situation happened in applications that used both high and normal priority interrupts together - check the errata for the chip you are using | 
 
 I'll begin afresh with my bughunting and report back on what I found
 
 Cheers for your help thus far.
 
 Andy
 |  |  
		|  |  
		| mbge5amw 
 
 
 Joined: 13 Dec 2004
 Posts: 15
 Location: Yorkshire, UK
 
 
			      
 
 | 
			
				|  |  
				|  Posted: Thu Feb 22, 2007 2:56 am |   |  
				| 
 |  
				| OK, I'm not sure now if the latest change I made (while systematically reducing the code size) has rectified the fault or simply masked the symptoms but it certainly looks to be behaving itself at the moment. 
 FYI what I found was a problem with my CAN bus comms.
 
 I have written a routine that takes the latest CAN bus command and puts it into a FIFO buffer.
 This routine first checks to see if there is space in the FIFO buffer, if there isn't space then it is left in the hardware buffer until space is made available - the idea being that the hardware will inform the transmitting device that it has no more room and so it should try later.
 
 This routine is called from each of the two CAN bus interrupts in order to get the fastest response possible most of the time.
 It is also called from the main loop in order to process any commands that were left in the hardware buffer during the ISR due to a full FIFO buffer.
 
 I did not want to have any of the variables used in this routine stomping on each other due to reentrancy so defined the code as inline so that 3 separate instances were made of it.
 Unfortunately I overlooked the fact that the final destination - i.e. the FIFO buffer was a global variable and this and its write pointer was referred to by all three instances of the routine.
 
 I have now removed the inline definition and the compiler is helpfully disabling interrupts while this is called in order to prevent reentrancy (with the added bonus of saving me a significant amount of code space)
 
 Ideally I would like to handle this myself with a flag that prevents recurrent execution of the code within the routine, thus I can still have the timer interrupts occuring in order to write steps to the stepper motor but that is a separate issue which I ought to be able to work out for myself.
 
 Thanks for listening to my ramblings.
 
 Andy
 |  |  
		|  |  
		|  |  
  
	| 
 
 | 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
 
 |