; ***************************************************************
; * Copyright (C) 2003, Embed Inc (http://www.embedinc.com) *
; * *
; * Permission to copy this file is granted as long as this *
; * copyright notice is included in its entirety at the *
; * beginning of the file, whether the file is copied in whole *
; * or in part and regardless of whether other information is *
; * added to the copy. *
; * *
; * The contents of this file may be used in any way, *
; * commercial or otherwise. This file is provided "as is", *
; * and Embed Inc makes no claims of suitability for a *
; * particular purpose nor assumes any liability resulting from *
; * its use. *
; ***************************************************************
;
; Top module for the QQ2 project. See the QQ2.INS.DSPIC include
; file for a description of the project.
;
/include "qq2.ins.dspic"
/block
/var local s string
/set s [str "Fosc = " [eng freq_osc oscdig] "Hz"]
/set s [str s ", Fcy = " [eng freq_inst oscdig] "Hz"]
/set s [str s ", Tcy = " [eng [/ 1 freq_inst] oscdig] "s"]
/show " " s
/endblock
/if [exist "fwtype"]
/then ;FWTYPE exists
/show " Firmware type ID = " fwtype
/else ;FWTYPE does not exist
/show " Firmware type ID not defined"
/endif
/if debug_icd then
/show " RealIce debugging enabled"
/endif
;*******************************************************************************
;
; Static processor configuration settings.
;
.section .configbits, code, address(0x557EC)
.pword 0xFFFFFF ;reserved
.pword 0xFFFFFF ;reserved
.pword 0b000000001111111111001111 ;FICD, 557F0
; 0000000011111111-------- unused, high 8 bits 0 makes NOP instruction
; ----------------1------- reserved, must be set to 1
; -----------------1------ unused
; ------------------0----- disable JTAG
; -------------------0---- reserved, must be set to 0
; --------------------1--- reserved, must be set to 1
; ---------------------1-- unused
; ----------------------11 ICD interface uses PGEC1/PGED1
.pword 0b000000001111111100110111 ;FPOR, 557F2
; 1111111111111111-------- unused, all 1s makes NOP instruction
; ----------------00------ WDT window is 75% of period
; ------------------1----- IIC2 uses SDA2/SCL2 pins
; -------------------1---- IIC1 users SDA1/SCL1 pins
; --------------------0--- disable brownout reset
; ---------------------111 unused
.pword 0b000000001111111101111111 ;FWDT, 557F4
; 1111111111111111-------- unused, all 1s makes NOP instruction
; ----------------0------- WDT not always enabled
; -----------------1------ WDT in non-window mode
; ------------------1----- enable PLL lock
; -------------------1---- WDT prescalser 128, not 32
; --------------------1111 WDT postscaler to max of 32768
.pword 0b000000001111111101011110 ;FOSC, 557F6
; 1111111111111111-------- unused, all 1s makes NOP instruction
; ----------------01------ clock switching enabled, failsafe clk disabled
; ------------------0----- allow multiple PPS changes
; -------------------11--- unused
; ---------------------1-- not used with external crystal oscillator
; ----------------------10 primary oscillator mode is HS
.pword 0b000000001111111100111010 ;FOSCSEL, 557F8
; 1111111111111111-------- unused, all 1s makes NOP instruction
; ----------------0------- start with selected osc mode, not FRC
; -----------------0------ don't require key sequence for PWM registers
; ------------------111--- unused
; ---------------------010 start with primary osc, not PLL
.pword 0b000000001111111111111111 ;FGS, 557FA
; 1111111111111111-------- unused, all 1s makes NOP instruction
; ----------------111111-- unused
; ----------------------1- disable user memory code protection
; -----------------------1 disable user memory write protection
.pword 0x00FFFF ;reserved, 557FC
.pword 0x00FFFF ;reserved, 557FE
;*******************************************************************************
;
; Reserve RAM for the ICD2. It needs exclusive control over the first 80
; bytes.
;
/if debug_icd then
.equiv __ICD2RAM, 1 ;linker reserves ICD RAM when this symbol defined
.global __ICD2RAM
/endif
;*******************************************************************************
;
; Define the global flag words. These are defined in near RAM so that bit
; manipulation instructions can be used on them directly. NFLAGB flag words
; need to be defined.
;
flags_define
;*******************************************************************************
;
; Constants in program memory so that HEX file editing tools know the version
; of this firmware.
;
.section .code_fwinfo, code, address(0x800)
.pword fwtype | (fwver << 8) | (fwseq << 16)
.section .code_strt, code
;*******************************************************************************
;
; Start of exeuctable code.
;
/if using_c
/then
glbent _main ;C runtime library jumps here after initialization
/else
glbent __reset ;jumps here directly from reset vector
/endif
;
; Initialize the interrupt system.
;
clr Iec0 ;disable all interrupts
.ifdef Iec1
clr Iec1
.endif
.ifdef Iec2
clr Iec2
.endif
.ifdef Iec3
clr Iec3
.endif
.ifdef Iec4
clr Iec4
.endif
.ifdef Ipc0 ;init all interrupt priorties to 0 (disabled)
clr Ipc0
.endif
.ifdef Ipc1
clr Ipc1
.endif
.ifdef Ipc2
clr Ipc2
.endif
.ifdef Ipc3
clr Ipc3
.endif
.ifdef Ipc4
clr Ipc4
.endif
.ifdef Ipc5
clr Ipc5
.endif
.ifdef Ipc6
clr Ipc6
.endif
.ifdef Ipc7
clr Ipc7
.endif
.ifdef Ipc8
clr Ipc8
.endif
.ifdef Ipc9
clr Ipc9
.endif
.ifdef Ipc10
clr Ipc10
.endif
.ifdef Ipc11
clr Ipc11
.endif
.ifdef Ipc12
clr Ipc12
.endif
.ifdef Ipc13
clr Ipc13
.endif
.ifdef Ipc14
clr Ipc14
.endif
.ifdef Ipc15
clr Ipc15
.endif
.ifdef Ipc16
clr Ipc16
.endif
.ifdef Ipc17
clr Ipc17
.endif
.ifdef Ipc18
clr Ipc18
.endif
.ifdef Ipc19
clr Ipc19
.endif
.ifdef Ipc20
clr Ipc20
.endif
clr Intcon1 ;initialize interrupt system to defaults
clr Intcon2
clr Sr ;make sure running with interrupt priority 0
.ifdef Gie
bset Intcon2, #Gie ;globally allow interrupts
.endif
flags_clear ;initialize all the global flags to off
;
; Set up the stack and the heap if the Embed DYMEM heap is in use. The linker
; is set up so that the suggested SPLIM value is the first address past the
; end of the stack. In other words, no guard band is reserved at the end of
; the stack. We set up the task 0 stack here with 6 bytes (3 words) of guard
; band.
;
/if dymem_heap ;set W0 to first address past the stack
/then ;using the Embed DYMEM heap, MINSTACK0 exists
mov #__SP_init + [v minstack0], w0
/else ;no heap, set up stack as defined by linker
mov #__SPLIM_init, w0
/endif
sub w0, #6, w1 ;make first stack address to causes trap when accessed
mov w1, Splim ;set hardware stack limit detector
nop ;needed after changing SPLIM
mov #__SP_init, w15 ;initialize the stack pointer
;
; Set up the Embed DYMEM heap, if enabled. W0 is the first address
; past the stack.
;
/if dymem_heap then ;set up the Embed DYMEM heap ?
mov #__SPLIM_init - 2, w1 ;pass adr of last word of the heap
gcall dymem_init ;init the heap
/endif
;
; Set up the system clock as defined in the LIB file. The processor is
; currently running directly from the external crystal. The PLL will be
; switched on.
;
; The following constants are set in the LIB file to define the clock
; chain:
;
; CLKPRE - PLL block prescaler divider, 2-33
; CLKMUL - PLL block multiplier, 2-513
; CLKPOS - PLL block postscaler divider, 2,4,8
;
;
; Set the CPU clock chain configuration as described above. This
; does not actually change the clock, but configures how the PLL
; block will work when it is enabled.
;
.set ii, #0b0000000000000000 ;init the fixed CLKDIV fields
; 0--------------- interrupts don't change doze mode
; -000------------ clock divided by 1 from normal in doze mode
; ----0----------- disable doze mode
; -----000-------- divide FRC by 1
; --------XX------ PLL output divide select filled in below
; ----------X----- unused
; -----------XXXXX PLL input divide select filled in below
.set ii, ii | ([- [div clkpos 2] 1] << 6) ;merge in PLL postscaler
.set ii, ii | [- clkpre 2] ;merge in PLL prescaler
mov #ii, w0
mov w0, Clkdiv ;set clock divisor register
mov #[- clkmul 2], w0 ;set PLL multiplier value
mov w0, Pllfbd
;
; Switch to using the primary oscillator with the PLL. We are
; currently using the primary oscillator without the PLL block. The
; designers of this clock chain hardware were paranoid about errant
; code unintentionally switching the clock, so certain incantations
; must be muttered to "unlock" the high and low bytes of OSCCON
; separately to allow the new information for switching the clock to
; be written.
;
mov #0b00000011, w0 ;get new value for OSCCON high byte
; X------- unused
; -XXX---- current oscillator selection (read only)
; ----X--- unused
; -----011 select primary oscillator with PLL
mov #Osccon+1, w1 ;set pointer to high byte of OSCCON
mov #0x78, w2 ;get the unlock values ready
mov #0x9A, w3
mov.b w2, [w1] ;write the high byte unlock sequence
mov.b w3, [w1]
mov.b w0, [w1] ;write new value to OSCCON high byte
mov #0b00000001, w0 ;get new value for OSCCON low byte
; 0------- do not disable clock switching
; -0------ allow peripheral pin select changes
; --X----- read-only status bit
; ---X---- unused
; ----0--- clear any clock failure detected (not used)
; -----X-- unused
; ------0- disable secondary low power oscillator
; -------1 start switchover from old to new clock source
mov #Osccon, w1 ;set pointer to low byte of OSCCON
mov #0x46, w2 ;get the unlock values ready
mov #0x57, w3
mov.b w2, [w1] ;write the low byte unlock sequence
mov.b w3, [w1]
mov.b w0, [w1] ;write new value to OSCCON low byte
/if [or [not debugging] debug_icd] then
wait_clkswitch: ;wait for clock switch
btsc Osccon, #Oswen ;oscillator switchover is complete ?
jump wait_clkswitch ;no, go back and check again
/endif
;
; Initialize the separate modules.
;
gcall trap_init ;init traps handler module
gcall port_init ;init I/O ports
gcall task_init ;init multi-tasking manager
gcall clock_init ;init clock tick hardware and ticks generator
gcall spi_init ;init SPI bus interface
gcall nvol_init ;init non-volatile memory access
gcall nvmem_ready ;check NV mem, erase if corrupt, set flags
gcall ad_init ;init A/D handler and start getting analog readings
gcall uart_init ;init low level UART driver
gcall cmd_init ;init host command stream processing module
gcall cmds_init ;init command routines module
gcall ledstat_init ;init Status LED controller
gjump init ;continue with system-wide initialization
.end