PIC ASM moving from Absolute to Relocatable mode - Page 1
Forum section: electronics / general

author: blewisjr
author_rank: Frequent Contributor
timestamp: May 02, 2013, 08:31:20 pm
content: Hello Everyone,I asked this question on the Microchip Forums but have not gotten a response yet so I decided to take a shot here as well.Obviously I started to learn PIC ASM through Absolute Mode as this is what the tutorials which came with my PICKit used.As I start to move to my own projects I realized I want a little more organization to the code as the projects iterate to larger firmware applications which helps design reusable code pieces across projects. To do this efficiently will less problems I found PIC ASM also supports Relocatable asm where the linker decides where to place everything in memory while still leaving you the ability to control where something goes if you have to.I did come across one issue that I have resolved which had to do with program entry.The Microchip documentation did aReset code 0x0000This actually generated an error saying reset was an op code so I modified the code to usereset_vec: code 0x0000To learn this new style of development I decided to return to the simple hello world blink led application.If anyone here has experience with PIC relocatable asm I am essentially looking for some best practices and tip to help me with the transition.The best way I can find for you to make suggestions would be to evaluate my hello world and show me where I made mistakes and how it could be done in a best practice way. Yes the code works perfectly but that does not mean I am doing things correctly in a way that would aid the transition.Code:; =============================================================================; Project: Hello World; Author:; Chip: PIC16F1829; Assembler: MPASM v5.49; Date: 5/2/2013; =============================================================================; =============================================================================; A simple program to blink an LED at a rate of approx. 1/2 second.; =============================================================================#include <p16f1829.inc>; Configure chip fuses#define CFG1A _FOSC_INTOSC & _WDTE_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _CPD_OFF#define CFG1B _BOREN_ON & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF__CONFIG _CONFIG1, CFG1A & CFG1B__CONFIG _CONFIG2, _WRT_OFF & _PLLEN_OFF & _STVREN_ON & _LVP_OFFradix decerrorlevel -302 ; turn off not in bank 0 warning; =========================================================================; Shared cross bank data; =========================================================================udata_shrcnt1 res 1cnt2 res 1; =========================================================================; Start up code; =========================================================================reset_vec: code 0x0000 ; Reset vectorpagesel startgoto startcodestart:movlw B'00111000' ; Set cpu clock to 500kHZbanksel OSCCON ; bank1movwf OSCCON ; Move w reg to OSCCONmovlw 0 ; Set cnt2 = 0movwf cnt2bcf TRISC, 0 ; In bank1 set PORTC0 as outputbanksel LATC ; bank2bsf LATC, 0 ; Turn on PORTC0 LEDcall delay_500ms ; 500ms Delaybcf LATC, 0 ; Turn off PORTC0 LEDcall delay_500ms ; 500ms Delaybra start ; Loop forever; =============================================================================; 500ms Delay loop actual speed is 0.50180 seconds.; Uses the equation {[(3 * cnt1 + 5) * cnt2] + 4} * 8uS; cnt1 = 80 and cnt2 = 256; =============================================================================delay_500ms:outer:movlw 80 ; Set cnt1 = 80movwf cnt1inner:decfsz cnt1, f ; Decrement cnt1 if zero skip branchbra innerdecfsz cnt2, f ; Decrement cnt2 if zero skip branchbra outerreturnend

author: croberts
author_rank: Regular Contributor
timestamp: May 03, 2013, 12:46:32 am
content: Hello blewisjrUsually the user memory shared space is reserved for interrupt context saving so you may want to get used to having variables in one of the banks and use banksel as required in case you want to do some interrupt routines. Software timers are a great way to do timers. You use Timer0 to generate an interrupt when it rolls over from ff to 00 and then do a combination of prescaling and loading a Timer0 start value to get the interrupt interval you want. The interrupt routine decrements the counters to 0 and then leaves them there and they are loaded with the desired time in your routines. You test them for 0 to get the desired time. If you are interested I can give you a template and some flowcharts.

author: blewisjr
author_rank: Frequent Contributor
timestamp: May 03, 2013, 02:10:59 am
content: No need for flowcharts I understand I can use a timer for this. I did this more as a quick and dirty check to see if I understand the core concepts of relocatable mode asm. Not even sure if I am going to use the PIC for this project yet. Thanks for that tip I can see why udata_shr could be very advantageous to interrupt register saving being that it can be accessed from any bank. Surprisingly this little excursion program taught me a lot about using the gnu assembler on avr instead of Atmel's because the gnu assembler is purely relocatable. Again thanks for the tip.