;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