Exemplo n.º 1
0
/** @brief Initialize GPIO pins
 *
 * @param[in] port uint32_t: GPIO Port base address
 * @param[in] pin uint32_t
 * @param[in] flags enum gpio_flags
 */
void gpio_init(uint32_t port, uint32_t pins, enum gpio_flags flags)
{
	switch (flags & 0x7) {
	case GPIO_FLAG_GPINPUT:
		PIO_ODR(port) = pins;
		PIO_PER(port) = pins;
		break;
	case GPIO_FLAG_GPOUTPUT:
		PIO_OER(port) = pins;
		PIO_PER(port) = pins;
		break;
	case GPIO_FLAG_PERIPHA:
		PIO_ABCDSR1(port) &= ~pins;
		PIO_ABCDSR2(port) &= ~pins;
		PIO_PDR(port) = pins;
		break;
	case GPIO_FLAG_PERIPHB:
		PIO_ABCDSR1(port) |= pins;
		PIO_ABCDSR2(port) &= ~pins;
		PIO_PDR(port) = pins;
		break;
	case GPIO_FLAG_PERIPHC:
		PIO_ABCDSR1(port) &= ~pins;
		PIO_ABCDSR2(port) |= pins;
		PIO_PDR(port) = pins;
		break;
	case GPIO_FLAG_PERIPHD:
		PIO_ABCDSR1(port) |= pins;
		PIO_ABCDSR2(port) |= pins;
		PIO_PDR(port) = pins;
		break;
	}

	if (flags & GPIO_FLAG_OPEN_DRAIN) {
		PIO_MDER(port) = pins;
	} else {
		PIO_MDDR(port) = pins;
	}

	if (flags & GPIO_FLAG_PULL_UP) {
		PIO_PUER(port) = pins;
	} else {
		PIO_PUDR(port) = pins;
	}
}
Exemplo n.º 2
0
void reset_handler() {
    // Disable Exceptions and Interrupts
    asm volatile ("cpsid f");
    asm volatile ("cpsid i");

    // Initialize the RTT and Event Timer
    timer_init();

    // Reset and Disable the Watchdog Timer
    WDT_CR = WDT_CR_WDRSTT | WDT_CR_KEY;
    WDT_MR = WDT_MR_WDDIS;

    // Enable Peripheral Clocks for the PIOs
    PMC_PCER = (1 << PMC_ID_PIOA);
    PMC_PCER = (1 << PMC_ID_PIOB);
    PMC_PCER = (1 << PMC_ID_PIOC);

    // Clear the PIO Interrupt Status Registers
    PIO_ISR(PIOA);
    PIO_ISR(PIOB);
    PIO_ISR(PIOC);

    // Configure the High-Voltage Pin and Disable the PSU (HV Off)
    PIO_PER(PIN_HV5530_HVEN_PIO)  = (1 << PIN_HV5530_HVEN_IDX); // Enable PIO on Pin
    PIO_OER(PIN_HV5530_HVEN_PIO)  = (1 << PIN_HV5530_HVEN_IDX); // Enable Output
    PIO_PUDR(PIN_HV5530_HVEN_PIO) = (1 << PIN_HV5530_HVEN_IDX); // Disable Pull-Up
    PIO_CODR(PIN_HV5530_HVEN_PIO) = (1 << PIN_HV5530_HVEN_IDX); // Clear Output Data Register

    // Configure the initial state of the 5v PSU (5v On)
    PIO_PER(PIN_5VPSU_EN_PIO)  = (1 << PIN_5VPSU_EN_IDX);    // Enable PIO on Pin
    PIO_OER(PIN_5VPSU_EN_PIO)  = (1 << PIN_5VPSU_EN_IDX);    // Enable Output
    PIO_PUER(PIN_5VPSU_EN_PIO) = (1 << PIN_5VPSU_EN_IDX);    // Enable Pull-Up
    PIO_CODR(PIN_5VPSU_EN_PIO) = (1 << PIN_5VPSU_EN_IDX);    // Clear Output Data Register

    // Configure the ZigBee Shutdown Pin (ZigBee On)
    PIO_PER(PIN_ZIGBEE_SHDN_PIO)  = (1 << PIN_ZIGBEE_SHDN_IDX); // Enable PIO on Pin
    PIO_OER(PIN_ZIGBEE_SHDN_PIO)  = (1 << PIN_ZIGBEE_SHDN_IDX); // Enable Output
    PIO_PUER(PIN_ZIGBEE_SHDN_PIO) = (1 << PIN_ZIGBEE_SHDN_IDX); // Enable Pull-Up
    PIO_SODR(PIN_ZIGBEE_SHDN_PIO) = (1 << PIN_ZIGBEE_SHDN_IDX); // Set Output Data Register

    // Enable User Resets by Asserting the NRST Pin
    // Assert NRST for 2^(11+1) Slow Clock Cycles (32 kHz * 4096 = 128ms)
    RSTC_MR = RSTC_MR_URSTEN | (11 << RSTC_MR_ERSTL_Off) | RSTC_MR_KEY;

    // Set the Flash Read/Write Cycles to 4 (for stable operation at 96MHz)
    EEFC_FMR(EEFC0) = ((EEFC_FMR(EEFC0) & ~EEFC_FMR_FWS_Msk) | (4 << (EEFC_FMR_FWS_Off)));
    EEFC_FMR(EEFC1) = ((EEFC_FMR(EEFC1) & ~EEFC_FMR_FWS_Msk) | (4 << (EEFC_FMR_FWS_Off)));

    // Configure Clock Generator Main Clock (External 12MHz Xtal)
    // Startup time 15625uS for Xtal (65 for 65*8 cycles at slow clock, ~32000Hz)
    CKGR_MOR = CKGR_MOR_KEY | (CKGR_MOR & ~(CKGR_MOR_MOSCXTBY)) |
        CKGR_MOR_MOSCXTEN | (65 << CKGR_MOR_MOSCXTST_Off);
    // Wait the main Xtal to stabilize
    while ((PMC_SR & PMC_SR_MOSCXTS) == 0);
    // Select Xtal as the Main Clock Source
    CKGR_MOR |= CKGR_MOR_KEY | CKGR_MOR_MOSCSEL;
    // Wait for the selection to complete
    while (!(PMC_SR & PMC_SR_MOSCSELS));

    // Configure Clock Generator PLLA Clock (12MHz Xtal * (15+1) = 192MHz)
    // Disable the PLL
    CKGR_PLLAR = CKGR_PLLAR_ONE;
    // Enable with the correct settings
    CKGR_PLLAR = CKGR_PLLAR_ONE | (1 << CKGR_PLLAR_DIVA_Off) |
        (15 << CKGR_PLLAR_MULA_Off) | (0x3F << CKGR_PLLAR_PLLACOUNT_Off);
    // Wait for a lock
    while (!(PMC_SR & PMC_SR_LOCKA));

    // Configure Clock Generator USB UTMI PLL (12MHz Xtal * 40 = 480MHz)
    // Enable the UTMI PLLA
    CKGR_UCKR = CKGR_UCKR_UPLLEN | (0xF << CKGR_UCKR_UPLLCOUNT_Off);
    // Wait for a lock
    while (!(PMC_SR & PMC_SR_LOCKU));

    // Configure Master Clock Controller (MCK = PLLA / 2 = 96MHz)
    // Program clock divider as 2
    PMC_MCKR = (PMC_MCKR & ~(PMC_MCKR_PRES_Msk)) | PMC_MCKR_PRES_CLK_2;
    // Program clock source as PLLA
    PMC_MCKR = (PMC_MCKR & ~(PMC_MCKR_CSS_Msk)) | PMC_MCKR_CSS_PLLA_CLK;
    // Wait for the master clock to be ready
    while (!(PMC_SR & PMC_SR_MCKRDY));

    // Zero the uninitialized data segment
    if (&bss_end - &bss_start > 0) {
        memset(&bss_start, 0, &bss_end - &bss_start);
    }

    // Load the initialized data segment
    if (&data_start != &data_load) {
        memcpy(&data_start, &data_load, &data_end - &data_start);
    }

    // Divide the interrupts into 4 groups of 4; 0-3, 4-7, 8-11, 12-15.
    // Interrupts within the same group will not preempt each other but an
    // interrupt from a group with a lower priority will. When two interrupts
    // within the same group are received at the same time, the one with the
    // lower priority number will be serviced first.
    AIRCR = AIRCR_VECTKEY | (0x5 << AIRCR_PRIGROUP_Off);

    // Set SVC Interrupt Priority to 4
    SHPR2 = ((SHPR2 & ~SHPR2_PRI_11_Msk) | (0x40 << SHPR2_PRI_11_Off));

    // Trap Divide-by-0 as Hard Fault
    CCR |= CCR_DIV_0_TRP;

    // Enable Exceptions
    asm volatile ("cpsie f");

    // Enable the Serial Console
    console_init();

    // Initialize the TWI Driver
    twi_init();

    // Enable Interrupts
    asm volatile ("cpsie i");

    // Print terminal headline
    kputs("\r\n\r\n");
    kputs("nixieclock-firmware: Nixie Clock Main Firmware Program\r\n");
    kputs("Copyright (C) 2013 - 2015 Joe Ciccone and Ed Koloski\r\n");
    kputs("This program comes with ABSOLUTELY NO WARRANTY; for details type 'license show'.\r\n");
    kputs("This is free software, and you are welcome to redistribute it\r\n");
    kputs("under certain conditions; type 'license show' for details.\r\n");
    kputs("\r\n");

    // Print the reset cause
    kputs("Reset Reason: ");
    switch (RSTC_SR & RSTC_SR_RSTTYP_Msk) {
    case RSTC_SR_RSTTYP_GENERAL:    kputs("General");   break;
    case RSTC_SR_RSTTYP_BACKUP:     kputs("Backup");    break;
    case RSTC_SR_RSTTYP_WATCHDOG:   kputs("Watchdog");  break;
    case RSTC_SR_RSTTYP_SOFTWARE:   kputs("Software");  break;
    case RSTC_SR_RSTTYP_USER:       kputs("User");      break;
    default:
        kprintf("Unknown (%lu)", ((RSTC_SR & RSTC_SR_RSTTYP_Msk) >> RSTC_SR_RSTTYP_Off));
    }
    kputs("\r\n");

    // Initialize Services
    clock_init();
    audio_init();
    display_init();
    keyboard_init();

    // Enable the Interactive Console
    console_start();

    // Play a sine-wave to debugging
    audio_play_sine();

    // Initialization Complete
    while (1) {}
}