5 Multiple Source Files, Paging and Linear Memory Example
In this PIC16F18446 example, the code reads a number of values from PORTC and stores these into the elements of an array accessed using linear memory addressing. Linear memory access is only implemented on Enhanced Mid-range devices, but other aspects of this code are relevant for all devices The example source code has been intentionally split into two files to illustrate how code can use routines and objects defined in other modules, and the consequences this has on how program memory pages must be handled.
Note: This code example performs manual masking of instruction
operand addresses to avoid fixup overflow errors. You can alternatively have the
linker automatically truncate operand values when building, as discussed in Working with Data Banks, so that the
BANKMASK()
and PAGEMASK()
macros used in this
example are not required.PIC16 Example - file_1.S
/*
* Take NUM_TO_READ samples of PORTC, storing this into an array accessed
* using linear memory. NUM_TO_READ must be defined as a macro on the command-line.
*/
PROCESSOR 16F18446
#include <xc.inc>
CONFIG "FEXTOSC = OFF" // External Oscillator not enabled
CONFIG "RSTOSC = HFINT1" // Power-up default value for COSC bits->HFINTOSC (1MHz)
CONFIG "CLKOUTEN = OFF" // CLKOUT disabled; i/o or oscillator on OSC2
CONFIG "CSWEN = ON" // Clock Switch Enable->Writing to NOSC and NDIV allowed
CONFIG "FCMEN = ON" // Fail-Safe Clock Monitor Enable->FSCM timer enabled
CONFIG "MCLRE = ON" // Master Clear Enable->MCLR pin is Master Clear function
CONFIG "PWRTS = OFF" // Power-up Timer Enable bit->PWRT disabled
CONFIG "LPBOREN = OFF" // Low-Power BOR enable bit->ULPBOR disabled
CONFIG "BOREN = ON" // Brown-out reset enable->Enabled, SBOREN bit is ignored
CONFIG "BORV = LO" // Brown-out Reset Voltage Selection->VBOR set to 2.45V
CONFIG "ZCDDIS = OFF" // Zero-cross circuit disabled at POR
CONFIG "PPS1WAY = ON" // PPSLOCK set/cleared only once
CONFIG "STVREN = ON" // Stack Over/Underflow causes reset
CONFIG "WDTCPS = WDTCPS_31" // WDT Period Divider 1:65536; software control
CONFIG "WDTE = OFF" // WDT operating mode->WDT Disabled, SWDTEN is ignored
CONFIG "WDTCWS = WDTCWS_7" // WDT Window always open; software control
CONFIG "WDTCCS = SC" // WDT input clock selector->Software Control
CONFIG "BBSIZE = BB512" // Boot Block Size Selection->512 words boot block size
CONFIG "BBEN = OFF" // Boot Block Enable bit->Boot Block disabled
CONFIG "SAFEN = OFF" // SAF Enable bit->SAF disabled
CONFIG "WRTAPP = OFF" // Application Block not write protected
CONFIG "WRTB = OFF" // Boot Block not write protected
CONFIG "WRTC = OFF" // Configuration Register not write protected
CONFIG "WRTD = OFF" // Data EEPROM write protection->Not write protected
CONFIG "WRTSAF = OFF" // Storage Area Flash not write protected
CONFIG "LVP = ON" // Low Voltage Programming Enabled, MCLR/Vpp pin is MCLR
CONFIG "CP = OFF" // UserNVM Program memory code protection disabled
PSECT code
;read PORTC, storing the result into WREG
readPort:
BANKSEL PORTC
movf BANKMASK(PORTC),w
return
GLOBAL count ;make this globally accessible
PSECT udata_shr
count:
DS 1 ;1 byte in common memory
PSECT resetVec,class=CODE,delta=2
resetVec:
PAGESEL main
goto main
GLOBAL storeLevel ;link in with global symbol defined elsewhere
PSECT code
main:
BANKSEL ANSELC
clrf BANKMASK(ANSELC)
clrf count
loop:
;a call to a routine in the same psect
call readPort ;value returned in WREG
;a call to a routine in a different module
PAGESEL storeLevel
call storeLevel ;expects argument in WREG
PAGESEL $
;wait for a few cycles
movlw 0xFF
delay:
decfsz WREG,f
goto delay
;increment the array index, count, and stop iterating
;when the final element is reached
movlw NUM_TO_READ
incf count,f
xorwf count,w
btfss ZERO
goto loop
goto $ ;loop forever
END resetVec
PIC16 Example - file_2.S
PROCESSOR 16F18446
#include <xc.inc>
GLOBAL storeLevel ;make this globally accessible
GLOBAL count ;link in with global symbol defined elsewhere
PSECT udata_shr
tmp:
DS 1
;define NUM_TO_READ bytes of linear memory, at banked address 0x120
DLABS 1,0x120,NUM_TO_READ,levels
PSECT code
;store byte passed via WREG into the count-th element of the
;linear memory array, levels
storeLevel:
movwf tmp ;store the parameter
movf count,w ;add the count index to...
addlw low(levels) ;the base address of the aray...
movwf FSR1L ;storing the result in FSR1
movlw high(levels)
clrf FSR1H
addwfc FSR1H
movf tmp,w ;retrieve the parameter
movwf INDF1 ;access levels in linear memory
return
END