; *************************************************************** ; * 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