;BEGIN initialization routine for the Atmel AtXMega64A1U
;NOTE: This is jumped-to directly from the MCU's Reset interrupt vector
;Written by E. Nicholas Cupery 07 October 2009
;
RESET: ldi XL, LOW(SRAM_STARTADR) ;lo-order starting address of SRAM
ldi XH,HIGH(SRAM_STARTADR) ;hi-order starting address of SRAM
ldi rByteLo, LOW(SRAM_BYTESIZE) ;lo-order number of bytes of SRAM
ldi rByteHi,HIGH(SRAM_BYTESIZE) ;hi-order number of bytes of SRAM
clr rTemp ;get a zero in a register
SRAM0: st X+,rTemp ;clear this one SRAM byte location
sbiw rByteLo,1 ;cleared all of SRAM yet?
brne SRAM0 ;br if no (loop)
lds rTemp,RST_STATUS ;read the Reset Status Register
sts sResetType,rTemp ;save the reset-type bits
ldi rTemp,$3F ;all reset-type bits
sts RST_STATUS,rTemp ;explicitly clear the reset-type flags
ldi XL, LOW(sStack) ;lo-order bottom address of stack
ldi XH,HIGH(sStack) ;hi-order bottom address of stack
ldi rCount,STACK_SIZE ;number of bytes of stack
ser rTemp ;get a -1 in a register
STACKI: st X+,rTemp ;initialize stack area to -1 flag value
dec rCount ;initialized 'em all yet?
brne STACKI ;br if no (loop)
ldi rTemp, LOW(sStackTop) ;lo-order starting address of stack
out SPL,rTemp ;load up the lo-order stack-pointer
ldi rTemp,HIGH(sStackTop) ;hi-order starting address of stack
out SPH,rTemp ;load up the hi-order stack-pointer
;will now set the port initial values
ldi rTemp,INITIAL_PORTA ;initial value for PORTA
sts PORTA_OUT,rTemp ;load it
ldi rTemp,INITIAL_PORTB ;initial value for PORTB
sts PORTB_OUT,rTemp ;load it
ldi rTemp,INITIAL_PORTC ;initial value for PORTC
sts PORTC_OUT,rTemp ;load it
ldi rTemp,INITIAL_PORTD ;initial value for PORTD
sts PORTD_OUT,rTemp ;load it
ldi rTemp,INITIAL_PORTE ;initial value for PORTE
sts PORTE_OUT,rTemp ;load it
ldi rTemp,INITIAL_PORTF ;initial value for PORTF
sts PORTF_OUT,rTemp ;load it
ldi rTemp,INITIAL_PORTH ;initial value for PORTH
sts PORTH_OUT,rTemp ;load it
ldi rTemp,INITIAL_PORTJ ;initial value for PORTJ
sts PORTJ_OUT,rTemp ;load it
ldi rTemp,INITIAL_PORTK ;initial value for PORTK
sts PORTK_OUT,rTemp ;load it
ldi rTemp,INITIAL_PORTQ ;initial value for PORTQ
sts PORTQ_OUT,rTemp ;load it
;will now set the port directions
ldi rTemp,DIRECTION_PORTA ;Port A bit-directions
sts PORTA_DIR,rTemp ;set all PortA bit directions
ldi rTemp,DIRECTION_PORTB ;Port B bit-directions
sts PORTB_DIR,rTemp ;set all PortB bit directions
ldi rTemp,DIRECTION_PORTC ;Port C bit-directions
sts PORTC_DIR,rTemp ;set all PortC bit directions
ldi rTemp,DIRECTION_PORTD ;Port D bit-directions
sts PORTD_DIR,rTemp ;set all PortD bit directions
ldi rTemp,DIRECTION_PORTE ;Port E bit-directions
sts PORTE_DIR,rTemp ;set all PortE bit directions
ldi rTemp,DIRECTION_PORTF ;Port F bit-directions
sts PORTF_DIR,rTemp ;set all PortF bit directions
ldi rTemp,DIRECTION_PORTH ;Port H bit-directions
sts PORTH_DIR,rTemp ;set all PortH bit directions
ldi rTemp,DIRECTION_PORTJ ;Port J bit-directions
sts PORTJ_DIR,rTemp ;set all PortJ bit directions
ldi rTemp,DIRECTION_PORTK ;Port K bit-directions
sts PORTK_DIR,rTemp ;set all PortK bit directions
ldi rTemp,DIRECTION_PORTQ ;Port Q bit-directions
sts PORTQ_DIR,rTemp ;set all PortQ bit directions
;will now set pullups on all input pins
ldi rTemp,PORT_OPC_PULLUP_gc;"totem-pole with pullup"
sts PORTC_PIN2CTRL,rTemp ;set pullup on "Rxd" input from HMI
sts PORTC_PIN6CTRL,rTemp ;set pullup on "Rxd" input from Logport
sts PORTD_PIN0CTRL,rTemp ;set pullup on TCoil input
sts PORTD_PIN6CTRL,rTemp ;set pullup on "Rxd" input from IRR
sts PORTF_PIN7CTRL,rTemp ;set pullup on S5VIO spare 5v I/O
sts PORTA_PIN1CTRL,rTemp ;set pullup on "Ack" pushbutton input
sts PORTA_PIN4CTRL,rTemp ;set pullup on "Event" pushbutton input
;will now check for Diagnostic-Mode ("Ack" button held down at reset)
clr rTemp ;get a zero in a register
lds rChar,MANUAL_ACK_PORT ;read the Manual-Ack port
andi rChar,MANUAL_ACK_BITP ;clear all but the "Manual Ack" bit
brne SETDIAG ;skip if "Ack" not pressed
ser rTemp ;change to non-zero value
SETDIAG:sts sDiagFlag,rTemp ;store the operating mode
;will now preload all timer countdown counters
ldi rTemp,TICKS_PER_MS ;# of fast-ticks per mS
sts sCountdown_mS,rTemp ;preload the mS timedown
ldi rTemp,10 ;full-count of ten
sts sCountdown_cS,rTemp ;preload the cS countdown counter
sts sCountdown_dS,rTemp ;preload the dS countdown counter
sts sCountdown_1S,rTemp ;preload the 1S countdown counter
;load up the timing parameters for Error-Number (yellow) LED flashing
ldi rTemp,FLASH_ON_TIME_10thS ;LED ON time (S/10)
sts sFlashOnTime,rTemp ;store it in SRAM
ldi rTemp,FLASH_OFF_TIME_10thS ;LED OFF time (S/10)
sts sFlashOffTime,rTemp ;store it in SRAM
ldi rTemp,FLASH_DELAY_TIME_10thS ;delay between flash cycles (S/10)
sts sFlashDelayTime,rTemp ;store it in SRAM
;setup Heartbeat (green) LED timing
ldi rTemp,BLINK_NORMAL_10thS;assume Normal operating mode
lds rTemp2,sDiagFlag ;fetch the Diagnostic-Mode flag
tst rTemp2 ;startup in Diagnostic-Mode?
breq NORMAL ;br if no
ldi rTemp,BLINK_WARNING_10thS ;warn about Diagnostic operating mode
NORMAL: sts sBlinkSTime_dS,rTemp ;load # of dS between LED blink toggles
sts sBlinkSTDown_dS,rTemp ;preload for the very first blink toggle
;initialize the HMI UART
ldi rTemp,LOW (BSEL_HMI) ;lo-order baud-selector
sts USARTC0_BAUDCTRLA,rTemp ;load it
ldi rTemp,HIGH(BSEL_HMI) ;hi-order baud-selector
sts USARTC0_BAUDCTRLB,rTemp ;load it
ldi rTemp,3 ;8-bit character size
sts USARTC0_CTRLC,rTemp ;load it
ldi rTemp,USART_RXEN_bm ;receiver-enable bit
ori rTemp,USART_TXEN_bm ;transmitter-enable bit
ori rTemp,USART_CLK2X_bm ;double-speed enable bit
sts USARTC0_CTRLB,rTemp ;start up the HMI UART
ldi rTemp,$10 ;LOW-level Receiver interrupts ONLY
sts USARTC0_CTRLA,rTemp ;set the interrupt level
;initialize the InfraRed Receiver UART
ldi rTemp,LOW (BSEL_IRR) ;lo-order baud-selector
sts USARTD1_BAUDCTRLA,rTemp ;load it
ldi rTemp,HIGH(BSEL_IRR) ;hi-order baud-selector
sts USARTD1_BAUDCTRLB,rTemp ;load it
ldi rTemp,7 ;9-bit character size
sts USARTD1_CTRLC,rTemp ;load it
ldi rTemp,USART_RXEN_bm ;receiver-enable bit
ori rTemp,USART_CLK2X_bm ;double-speed enable bit
sts USARTD1_CTRLB,rTemp ;start up the IRR UART
ldi rTemp,$30 ;HIGH-level Receiver interrupts ONLY
sts USARTD1_CTRLA,rTemp ;set the interrupt level
;initialize the Logging UART
ldi rTemp,LOW (BSEL_LOG) ;lo-order baud-selector
sts USARTC1_BAUDCTRLA,rTemp ;load it
ldi rTemp,HIGH(BSEL_LOG) ;hi-order baud-selector
sts USARTC1_BAUDCTRLB,rTemp ;load it
ldi rTemp,3 ;8-bit character size
sts USARTC1_CTRLC,rTemp ;load it
ldi rTemp,USART_RXEN_bm ;receiver-enable bit
ori rTemp,USART_TXEN_bm ;transmitter-enable bit
ori rTemp,USART_CLK2X_bm ;double-speed enable bit
sts USARTC1_CTRLB,rTemp ;start up the Logging UART
;will now switch from internal 2MHz oscillator to external crystal
ldi rTemp,HEARTBEAT_BITP ;heartbeat LED bit pattern
sts HB_OUTCLR_PORT,rTemp ;temporarily turn ON the green LED
ldi rTemp,OSC_FRQRANGE_2TO9_gc ;frequency range 2 - 9 MHz
ori rTemp,OSC_XOSCSEL_XTAL_16KCLK_gc;normal quartz crystal
sts OSC_XOSCCTRL,rTemp ;load the XOSC Control Register
ldi rTemp,OSC_XOSCEN_bm ;"external OSC Enable"
sts OSC_CTRL,rTemp ;enable the external OSC (crystal)
OSCWAIT:lds rTemp,OSC_STATUS ;read the XOSC Status Register
andi rTemp,OSC_XOSCRDY_bm ;clear all but "External Osc Ready"
breq OSCWAIT ;br if XOSC not ready yet
ldi rTemp,OSC_PLLSRC_XOSC_gc ;"PLL source is XOSC"
ori rTemp,8 ;and multiply by 8
sts OSC_PLLCTRL,rTemp ;select XOSC as 8x PLL source
ldi rTemp,OSC_PLLEN_bm ;"PLL Enable"
ori rTemp,OSC_XOSCEN_bm ;keep "XOSC Enable"
sts OSC_CTRL,rTemp ;enable the PLL
PLLWAIT:lds rTemp,OSC_STATUS ;read the XOSC Status Register
andi rTemp,OSC_PLLRDY_bm ;clear all but "PLL Ready"
breq PLLWAIT ;br if PLL not ready yet
ldi rTemp,0xD8 ;change-protection signature
sts CPU_CCP,rTemp ;allow changes within 4 clocks
ldi rTemp,CLK_SCLKSEL_PLL_gc ;"select External Clock"
sts CLK_CTRL,rTemp ;select the crystal
ldi rTemp,HEARTBEAT_BITP ;heartbeat LED bit pattern
sts HB_OUTSET_PORT,rTemp ;turn OFF the green LED
;flag the reboot with flashing of the yellow LED
ldi rTemp,FLASH_REBOOT ;flash-count for this condition
call FLASHNUM ;flash this code, if is the highest yet
;will now set the Timer0 interrupt level
ldi rTemp,TC_OVFINTLVL_MED_gc ;MEDIUM interrupt level for Timer0
sts TCC0_INTCTRLA,rTemp ;set the interrupt level
;will now set up the Timer0 timer period
ldi rByteLo,LOW (Timer0_Count) ;lo-order timer period
ldi rByteHi,HIGH(Timer0_Count) ;hi-order timer period
sts TCC0_PER+0,rByteLo ;load lo-order timer period register
sts TCC0_PER+1,rByteHi ;load hi-order timer period register
;will now start Timer0 by telling it it's clock source
ldi rTemp,TIMER0_PRESCALE ;system clock divided by 64
sts TCC0_CTRLA,rTemp ;start Timer0
;will now enable the interrupt system
ldi rTemp,PMIC_HILVLEN_bm ;"enable high-level interrupts"
ori rTemp,PMIC_MEDLVLEN_bm ;"enable medium-level interrupts"
ori rTemp,PMIC_LOLVLEN_bm ;"enable low-level interrupts"
sts PMIC_CTRL,rTemp ;enable interrupt levels
;will now check out the external SRAM
call XSRAMCHK ;run XSRAM diagnostic
;will now load any general register that is DEDICATED
;NOTE: System Reset does NOT clear general registers
clr rPendingState ;no breaker Pending-State yet
;will now enable the Watchdog-Timer
ldi rTemp,$D8 ;protection signature for I/O registers
out CPU_CCP,rTemp ;disable protection for 4 CPU cycles
ldi rTemp,$1F ;Watchdog-Enable + timer period (64 mS)
sts WDT_CTRL,rTemp ;enable the watchdog timer
sei ;globally enable interrupts
rjmp MAINLOOP ;now enter main program loop
;
;END initialization example code for an Atmel AtXMega64A1U