' Getting started with AT91SAM7S devices ' Port to HBBR Basic ' Copyright (c) 20072-008, Hobby-Robotics, LLC ' Copyright notice in the original C based code '/* ---------------------------------------------------------------------------- ' * ATMEL Microcontroller Software Support - ROUSSET - ' * ---------------------------------------------------------------------------- ' * Copyright (c) 2006, Atmel Corporation ' * ' * All rights reserved. ' * ' * Redistribution and use in source and binary forms, with or without ' * modification, are permitted provided that the following conditions are met: ' * ' * - Redistributions of source code must retain the above copyright notice, ' * this list of conditions and the disclaiimer below. ' * ' * - Redistributions in binary form must reproduce the above copyright notice, ' * this list of conditions and the disclaimer below in the documentation and/or ' * other materials provided with the distribution. ' * ' * Atmel's name may not be used to endorse or promote products derived from ' * this software without specific prior written permission. ' * ' * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR ' * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ' * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE ' * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, ' * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ' * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, ' * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ' * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING ' * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, ' * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ' * ---------------------------------------------------------------------------- ' */ ' Global variables Const LED_A As Integer = &B0001 ' PA0 AT91B_LED1 Const LED_B As Integer = &B0010 ' PA1 AT91B_LED2 Const BUTTON_A As Integer = &B010000000000000000000 ' PA19 AT91B_BP1 Const BUTTON_B As Integer = &B100000000000000000000 ' PA20 AT91B_BP2 Const ID_PIO_BP As Integer = &H2 ' AT91D_ID_PIO_SW = AT91C_ID_PIOA Const DEBOUNCE_TIME As Integer = 500 ' The following global variables, control the LED blinking Dim led_a_active As Boolean = True Dim led_b_active As Boolean = True Dim jiffies As Integer = 0 '----------------------------------------------------------------------------- ' * Function Name : pabt_handler ' * Object : Prefetch Abort Handler ' *--------------------------------------------------------------------------- ' ' Currently custom Prefetch Abort Handler can not be installed by the user ' Irq pabt_handler() Call dbgu_print_ascii("-F- Prefetch abort at ") Call dbgu_print_hex8(AT91C_MC_AASR) Call dbgu_print_ascii("\n\r") End Irq '----------------------------------------------------------------------------- ' * Function Name : dabt_handler ' * Object : Data Abort Handler ' *--------------------------------------------------------------------------- ' ' Currently custom Data Abort Handler can not be installed by the user ' Irq dabt_handler() Call dbgu_print_ascii("-F- Data abort at ") Call dbgu_print_hex8(AT91C_MC_AASR) Call dbgu_print_ascii("\n\r") End Irq '----------------------------------------------------------------------------- ' * Function Name : pitc_handler ' * Object : Handler for PITC interrupt ' *--------------------------------------------------------------------------- Irq pitc_handler() Dim pivr As Integer = 0 Dim pisr As Integer = 0 ' Read the PISR pisr = AT91C_PITC_PISR And AT91C_PITC_PITS If (pisr <> 0) Then ' Read the PIVR. It acknowledges the IT pivr = AT91C_PITC_PIVR ' Add to jiffies PICNT: the number of occurrences of periodic intervals ' since the last read of PIT_PIVR jiffies = jiffies + (pivr >> 20) End If End Irq '----------------------------------------------------------------------------- ' * Function Name : configure_pit ' * Object : Configure priodic interval timer ' *--------------------------------------------------------------------------- Sub configure_pit() Dim pimr As Integer = 0 ' Configure a resolution of 1 ms AT91C_PITC_PIMR = __conf_MCK \ (16 * 1000) - 1 ' AT91B_MASTER_CLOCK ' Enable interrupts ' Disable the interrupt on the interrupt controller AT91C_AIC_IDCR = (1 << AT91C_ID_SYS) ' Save the interrupt handler routine pointer and the interrupt priority ' AT91C_AIC_SVR[AT91C_ID_SYS] = pitc_handler AT91C_AIC_SVR1 = CInt(AddressOf pitc_handler) ' AT91C_ID_SYS = &H1 ' Store the Source Mode Register ' AT91C_AIC_SMR[AT91C_ID_SYS] = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL Or AT91C_AIC_PRIOR_LOWEST AT91C_AIC_SMR1 = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL Or AT91C_AIC_PRIOR_LOWEST ' AT91C_ID_SYS = &H1 ' Clear the interrupt on the interrupt controller AT91C_AIC_ICCR = (1 << AT91C_ID_SYS) ' Enable the interrupt on the interrupt controller AT91C_AIC_IECR = (1 << AT91C_ID_SYS) ' Enable the interrupt on the pit pimr = AT91C_PITC_PIMR AT91C_PITC_PIMR = pimr Or AT91C_PITC_PITIEN ' Enable the pit pimr = AT91C_PITC_PIMR AT91C_PITC_PIMR = pimr Or AT91C_PITC_PITEN End Sub '----------------------------------------------------------------------------- ' * Function Name : button_handler ' * Object : Button Interrupt Service Routine (PIO A) ' *--------------------------------------------------------------------------- Irq button_handler() ' Read the Interrupt Status register (It acknowledge the IT) Dim pio_isr As Integer ' = AT91C_PIOA_ISR Dim pio_pdsr As Integer ' = AT91C_PIOA_PDSR Dim button_a_jiffies As Integer = 0 Dim button_b_jiffies As Integer = 0 pio_isr = AT91C_PIOA_ISR pio_pdsr = AT91C_PIOA_PDSR ' If the BUTTON_A has been pushed or released If (CBool(pio_isr And BUTTON_A)) Then ' Enable/disable the LED A blinking when BUTTON_A is released If (CBool(pio_pdsr And BUTTON_A))Then If (jiffies - button_a_jiffies > DEBOUNCE_TIME) Then button_a_jiffies = jiffies led_a_active = Not led_a_active End If End If ' If the BUTTON_B has been pushed or released ElseIf (CBool(pio_isr And BUTTON_B)) Then ' Enable/disable the LED B blinking when BUTTON_B is pushed If (Not CBool(pio_pdsr And BUTTON_B)) Then If (jiffies - button_b_jiffies > DEBOUNCE_TIME) Then button_b_jiffies = jiffies If (led_b_active) Then ' Disable the clock AT91C_TC0_CCR = AT91C_TC_CLKDIS Else ' Clock is started AT91C_TC0_CCR = AT91C_TC_CLKEN ' Counter is reset and the clock is started AT91C_TC0_CCR = AT91C_TC_SWTRG End If led_b_active = Not led_b_active End If End If ' The Else should not be executed since no other PIO are enabled Else End If End Irq '----------------------------------------------------------------------------- ' * Function Name : configure_buttons ' * Object : Configure pios to capture buttons state ' *--------------------------------------------------------------------------- Sub configure_buttons() ' Enable the periph clock for the PIO controller ' This is mandatory when PIO are configured as input AT91C_PMC_PCER = (1 << ID_PIO_BP) ' Set the PIO line in input AT91C_PIOA_ODR = (BUTTON_A Or BUTTON_B) ' Set the PIO controller in PIO mode instead of peripheral mode AT91C_PIOA_PER = (BUTTON_A Or BUTTON_B) ' Disable the interrupt on the interrupt controller AT91C_AIC_IDCR = (1 << ID_PIO_BP) ' Save the interrupt handler routine pointer and the interrupt priority ' TBI AT91C_AIC_SVR[ID_PIO_BP] = button_handler AT91C_AIC_SVR2 = CInt(AddressOf button_handler) ' ID_PIO_BP AT91C_ID_PIOA = &H2 ' Store the Source Mode Register ' AT91C_AIC_SMR[ID_PIO_BP] = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL Or AT91C_AIC_PRIOR_LOWEST AT91C_AIC_SMR2 = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL Or AT91C_AIC_PRIOR_LOWEST ' ID_PIO_BP AT91C_ID_PIOA = &H2 ' Clear the interrupt on the interrupt controller AT91C_AIC_ICCR = (1 << ID_PIO_BP) ' Enable button interrupts generation through the PIO controller AT91C_PIOA_IER = (BUTTON_A Or BUTTON_B) ' Enable PIO interrupt in the interrupt controller AT91C_AIC_IECR = (1 << ID_PIO_BP) End Sub '----------------------------------------------------------------------------- ' * Function Name : configure_leds ' * Object : Configure pios to control led states ' *--------------------------------------------------------------------------- Sub configure_leds() ' Configure the pin in output AT91C_PIOA_OER = (LED_A Or LED_B) ' Set the PIO controller in PIO mode instead of peripheral mode AT91C_PIOA_PER = (LED_A Or LED_B) ' Disable pull-up AT91C_PIOA_PPUDR = (LED_A Or LED_B) ' Set the default state for the led If (led_a_active) Then AT91C_PIOA_SODR = LED_A Else AT91C_PIOA_CODR = LED_A End If If (led_b_active) Then AT91C_PIOA_SODR = LED_B Else AT91C_PIOA_CODR = LED_B End If End Sub '----------------------------------------------------------------------------- ' * Function Name : timer_handler ' * Object : Handler for TC interrupt ' *--------------------------------------------------------------------------- Irq timer_handler() Dim dummy As Integer ' Clear status bit dummy = AT91C_TC0_SR ' Toggle LED state If (AT91C_PIOA_ODSR And LED_B) Then AT91C_PIOA_CODR = LED_B Else AT91C_PIOA_SODR = LED_B End If End Irq '----------------------------------------------------------------------------- ' * Function Name : configure_tc ' * Object : Configure TC ' *--------------------------------------------------------------------------- Sub configure_tc() Dim dummy As Integer ' Enable periph clock for the PIO controller AT91C_PMC_PCER = (1 << AT91C_ID_TC0) ' Enable the periph ' Disable the clock and the interrupts AT91C_TC0_CCR = AT91C_TC_CLKDIS AT91C_TC0_IDR = &HFFFFFFFF ' Clear status bit dummy = AT91C_TC0_SR ' Set the Mode of the Timer Counter AT91C_TC0_CMR = AT91C_TC_CLKS_TIMER_DIV5_CLOCK Or AT91C_TC_CPCTRG AT91C_TC0_RC = __conf_MCK >> 12 ' MCKR divided by 1024 * 4 AT91B_MASTER_CLOCK ' Enable interrupts ' Disable the interrupt on the interrupt controller AT91C_AIC_IDCR = (1 << AT91C_ID_TC0) ' Save the interrupt handler routine pointer and the interrupt priority ' AT91C_AIC_SVR[AT91C_ID_TC0] = timer_handler AT91C_AIC_SVR12 = AddressOf timer_handler ' AT91C_ID_TC0 = 12 ' Store the Source Mode Register ' AT91C_AIC_SMR[AT91C_ID_TC0] = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL Or AT91C_AIC_PRIOR_LOWEST AT91C_AIC_SMR12 = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL Or AT91C_AIC_PRIOR_LOWEST ' Clear the interrupt on the interrupt controller AT91C_AIC_ICCR = (1 << AT91C_ID_TC0) AT91C_TC0_IER = AT91C_TC_CPCS ' Enable the interrupt on the interrupt controller AT91C_AIC_IECR = (1 << AT91C_ID_TC0) ' Enable the LED B timer If (led_b_active) Then ' Clock is started AT91C_TC0_CCR = AT91C_TC_CLKEN ' Counter is reset and the clock is started AT91C_TC0_CCR = AT91C_TC_SWTRG End If End Sub '---------------------------------------------------------------------------- ' * Function Name : dbgu_print_ascii ' * Object : This function is used to send a string through the ' * DBGU channel (Very low level debugging) ' *-------------------------------------------------------------------------- Sub dbgu_print_ascii( buffer$ As String ) Dim l As Integer Dim i As Integer i = 1 l = Len(buffer$) Do While (i <= l) Do While (Not CBool((AT91C_DBGU_CSR And AT91C_US_TXRDY))) Loop AT91C_DBGU_THR = ( Asc(Mid$(buffer$,i,1)) And &H1FF ) i = i + 1 Loop End Sub '---------------------------------------------------------------------------- ' * Function Name : dbgu_print_hex8 ' * Object : This function is used to print a 32-bit value in hex ' *--------------------------------------------------------------------------- Sub dbgu_print_hex8(value As Integer) Dim c As Byte = 0 Dim shift As Byte = 32 '= sizeof(unsigned long) * 8 Call dbgu_print_ascii("&H") Do shift = shift - 4 Do While (Not CBool((AT91C_DBGU_CSR And AT91C_US_TXRDY))) Loop c = ((value >> shift) And &HF) If (c > 9) Then AT91C_DBGU_THR = ((Asc("A") + (c - 10)) And &H1FF) Else AT91C_DBGU_THR = ((Asc("0") + c) And &H1FF) End If Loop While (shift <> 0) End Sub '----------------------------------------------------------------------------- ' * Function Name : configure_dbgu ' * Object : Configure DBGU ' *--------------------------------------------------------------------------- ' ' Re-configuring DBGU can lead to lost sync between PC and AT91SAM7-EK board. ' Since HBBR runtime is configuring the DBGU there is no need to do it again ' Sub configure_dbgu () ' Reset and disable receiver AT91C_DBGU_CR = AT91C_US_RSTRX Or AT91C_US_RSTTX ' Disable interrupts AT91C_DBGU_IDR = &HFFFFFFFF ' Configure PIOs for DBGU AT91C_PIOA_ASR = AT91C_PA9_DRXD Or AT91C_PA10_DTXD AT91C_PIOA_BSR = 0 AT91C_PIOA_PDR = AT91C_PA9_DRXD Or AT91C_PA10_DTXD ' === Configure serial link === ' Define the baud rate divisor register [BRGR = MCK / (115200 * 16)] ' Default baud rate for HBBR Basic IDE is 38400 AT91C_DBGU_BRGR = __conf_MCK / (38400 * 16) ' Define the USART mode AT91C_DBGU_MR = AT91C_US_PAR_NONE Or AT91C_US_CHMODE_NORMAL ' Disable the RX and TX PDC transfer requests AT91C_DBGU_PTCR = AT91C_PDC_RXTDIS AT91C_DBGU_PTCR = AT91C_PDC_TXTDIS ' Enable transmitter AT91C_DBGU_CR = AT91C_US_TXEN End Sub '----------------------------------------------------------------------------- ' * Function Name : wait ' * Object : Tempo using jiffies (updated by PITC) ' *--------------------------------------------------------------------------- Sub wait (ms As Integer) Dim current_time As Integer Dim prev_jiffies As Integer Dim target_time As Integer current_time = jiffies target_time = current_time + ms ' Handle the counter overflow If (target_time < current_time) Then prev_jiffies = current_time Do While (prev_jiffies <= jiffies) prev_jiffies = jiffies Loop End If ' Loop until the target time is reached Do While (jiffies < target_time) Loop End Sub Sub dump_CONF() Print #0, "MCK :";__conf_MCK Print #0, "CSS :";__conf_CSS Print #0, "PRES :";__conf_PRES Print #0, "MAINCK :";__conf_MAINCK Print #0, "SLCK :";__conf_SLCK Print #0, "PLLCK :";__conf_PLLCK Print #0, "DIV :";__conf_DIV Print #0, "MUL :";__conf_MUL Print #0, "PCK :";__conf_PCK Print #0, "UDPCK :";__conf_UDPCK Print #0, "USBDIV :";__conf_USBDIV End Sub Sub Main() ' ==== Dump MOD configuration ==== Call dump_CONF() ' ==== PITC configuration ==== Call configure_pit() ' ==== Timer Counter configuration ==== Call configure_tc() ' === BUTTON configuration (PIO in INPUT) === Call configure_buttons() ' === LED configuration (PIO in OUTPUT) === Call configure_leds() ' ==== DBGU configuration ==== ' DBGU is configured by the HBBR runtime ' ' Call configure_dbgu() Call dbgu_print_ascii("AT91SAM7S Getting Started program launched ...") Call dbgu_print_ascii(Chr$(CR)) Call dbgu_print_ascii(Chr$(LF)) Call dbgu_print_ascii("AT91SAM7S chip ID : ") Call dbgu_print_hex8(AT91C_DBGU_CIDR) Call dbgu_print_ascii(Chr$(CR)) Call dbgu_print_ascii(Chr$(LF)) ' Enable interrupts Call __hbbr_enable_irq() Do While (1) If (led_a_active) Then ' Switch on the led Call wait(500) AT91C_PIOA_CODR = LED_A ' Switch off the led Call wait(500) AT91C_PIOA_SODR = LED_A End If Loop End Sub