void ADCInit(void) { int channel; /* Only init once */ if (ADC_Buffer) return; /* Enable clock int PMC and reset ADC */ outr(PMC_PCER, _BV(ADC_ID)); // Enable ADC clock in PMC outr(ADC_CR, ADC_SWRST); // Reset bus outr(ADC_CR, 0x00); /* Basic configuration: Disable all channels and set mode and prescaler */ outr(ADC_CHDR, ADC_CH0 | ADC_CH1 | ADC_CH2 | ADC_CH3 | ADC_CH4 | ADC_CH5 | ADC_CH6 | ADC_CH7); ADCSetMode(AT91_ADC_INITIAL_MODE); ADCSetPrescale(AT91_ADC_INITIAL_PRESCALE); /* Init adc buffers. One for every channel as we can sample all by automatic sequence */ ADC_Buffer = NutHeapAlloc(sizeof(uint16_t *) * ADC_MAX_CHANNEL); for (channel = 0; channel < ADC_MAX_CHANNEL; channel ++) { ADC_Buffer[channel] = NutHeapAlloc(sizeof(uint16_t) * AT91_ADC_BUF_SIZE + 2); ADC_Buffer[channel][_adc_buf_head] = 0; ADC_Buffer[channel][_adc_buf_tail] = 0; } if (NutRegisterIrqHandler(&sig_ADC, ADCInterrupt, NULL)) { // We do not free buffer as this would cost ROM and is not likely return; } NutIrqEnable(&sig_ADC); }
/*! * \brief Initialize system timer. * * This function is automatically called by Nut/OS * during system initialization. * * Nut/OS uses on-chip timer 0 for its timer services. * Applications should not modify any registers of this * timer, but make use of the Nut/OS timer API. Timer 1 * and timer 2 are available to applications. */ void NutTimerInit(void) { #ifdef NUT_CPU_FREQ /* 16 bit timer ch. 0 high priority */ INTC.IPRA.BIT._ITU0 = 1; /* auto clear TCNT, clock is phi/4 */ ITU0.TCR.BYTE = 0x22; /* no output on GRA */ ITU0.TIOR.BYTE = 0x00; /* generate interrupt every 10ms */ /* ITU0.GRA = 0xd7ff; */ /* generate interrupt every 1ms */ ITU0.GRA = 0x159a; /* clear counter register */ ITU0.TCNT = 0x0000; /* enable IMIA0 interrupt */ ITU.TISRA.BIT.IMIEA0 = 1; NutRegisterIrqHandler(&sig_IMIA0, NutTimer0Intr, 0); /* start timer 0 */ ITU.TSTR.BIT.STR0 = 1; #else /* #ifdef NUT_CPU_FREQ */ /* TODO !!! */ #error "NUT_CPU_FREQ must be defined" #endif /* #ifdef NUT_CPU_FREQ */ }
/*! * \brief Initialize the RTC in LPC 17xx controller * * \return 0 on success or -1 in case of an error. * */ static int Lpc17xxRtcInit(NUTRTC *rtc) { rtc->dcb = NutHeapAllocClear(sizeof(lpc17xx_rtc_dcb)); if (rtc->dcb == NULL) { return -1; } if (NutRegisterIrqHandler(&sig_RTC, Lpc17xxRtcInterrupt, rtc) != 0) { NutHeapFree(rtc->dcb); return -1; } /* Set up clock and power for RTC module */ SysCtlPeripheralClkEnable(CLKPWR_PCONP_PCRTC); /* Clear all register to be default */ LPC_RTC->ILR = 0x03; LPC_RTC->CCR = 0x00; LPC_RTC->CIIR = 0x00; LPC_RTC->AMR = 0xFF; LPC_RTC->CALIBRATION = 0x00; /* enable RTC (run) */ LPC_RTC->CCR |= RTC_CCR_CLKEN; ((lpc17xx_rtc_dcb *)rtc->dcb)->flags = 0x00000000; rtc->alarm = NULL; NutIrqEnable(&sig_RTC); return(0); }
/*! * \brief Initialize TWI interface. * * The specified slave address is used only, if the local system * is running as a slave. Anyway, care must be taken that it doesn't * conflict with another connected device. * * \note This function is only available on ATmega128 systems. * * \param sla Slave address, must be specified as a 7-bit address, * always lower than 128. */ int TwInit(u_char sla) { #ifndef __AVR_ENHANCED__ return -1; #else u_long speed = 2400; if (NutRegisterIrqHandler(&sig_2WIRE_SERIAL, TwInterrupt, 0)) { return -1; } /* * Set address register, enable general call address, set transfer * speed and enable interface. */ outb(TWAR, (sla << 1) | 1); TwIOCtl(TWI_SETSPEED, &speed); outb(TWCR, _BV(TWINT)); outb(TWCR, _BV(TWEN) | _BV(TWIE)); /* * Initialize mutex semaphores. */ NutEventPost(&tw_mm_mutex); return 0; #endif /* __AVR_ENHANCED__ */ }
/*! * \brief Initialize the second serial peripheral interface on the AT91 MCU. */ int At91Spi1Init(void) { /* Enable SPI peripherals. */ At91Spi1Enable(); /* Enable SPI clock. */ outr(PMC_PCER, _BV(SPI1_ID)); /* Register and enable SPI1 interrupt handler. */ NutRegisterIrqHandler(&sig_SPI1, At91Spi1Interrupt, 0); NutIrqEnable(&sig_SPI1); return At91SpiReset(SPI1_BASE); }
/*! * \brief Initialize the first serial peripheral interface on the AVR32 MCU. */ int Avr32Spi0Init(void) { volatile avr32_spi_t *spi = AVR32_SPI0; /* Enable SPI peripherals. */ Avr32Spi0Enable(); /* Enable SPI clock. */ spi->outr(PMC_PCER, _BV(SPI0_ID)); /* Register and enable SPI0 interrupt handler. */ NutRegisterIrqHandler(&sig_SPI0, Avr32Spi0Interrupt, 0); NutIrqEnable(&sig_SPI0); return Avr32SpiReset(SPI0_BASE); }
/*! * \brief Initialize the I2C bus controller (STM32 implementation). * * This function is called by the platform independent code via the * NUTI2C_BUS::bus_init function pointer when the first slave is * attached to this bus. Note, that NUTI2C_BUS::bus_rate must be zero * initially. Otherwise no call to this function will take place. * * This function must do all required initializations so that the * driver will be ready to process transfers via NUTI2C_BUS::bus_tran. * * This function must return 0 on success or -1 otherwise. */ static int I2cBusInit(NUTI2C_BUS *bus) { I2C_TypeDef *i2c; STM32_I2CCB *icb; icb = (STM32_I2CCB *) bus->bus_icb; if (checkpin_and_config(icb)) return -1; /* Try to configure the bus*/ if (I2cBusConf(bus)) { return -1; } i2c = (I2C_TypeDef*) icb->icb_base; i2c->CR1 |= I2C_CR1_PE; if (NutRegisterIrqHandler(icb->icb_sig_ev, I2cEventBusIrqHandler, icb)) return -1; if (NutRegisterIrqHandler(icb->icb_sig_er, I2cErrorBusIrqHandler, icb)) return -1; NutIrqEnable(icb->icb_sig_ev); NutIrqDisable(icb->icb_sig_er); return 0; }
static void SysControlMainBeat(u_char OnOff) { int nError = 0; if (OnOff==ON) { nError = NutRegisterIrqHandler(&OVERFLOW_SIGNAL, SysMainBeatInterrupt, NULL); if (nError == 0) { init_8_bit_timer(); } } else { // disable overflow interrupt disable_8_bit_timer_ovfl_int(); } }
/*! * \brief Initialize system timer. * * This function is automatically called by Nut/OS * during system initialization. * * Nut/OS uses on-chip timer 0 for its timer services. * Applications should not modify any registers of this * timer, but make use of the Nut/OS timer API. Timer 1 * and timer 2 are available to applications. */ void NutRegisterTimer(void (*handler) (void *)) { os_handler = handler; /* Disable master interrupt. */ outw(REG_IME, 0); /* Set global interrupt vector. */ NutRegisterIrqHandler(&sig_TMR3, Timer3Entry, 0); /* Enable timer and timer interrupts. */ outdw(REG_TMR3CNT, TMR_IRQ_ENA | TMR_ENA | 48756); /* Enable timer 3 interrupts. */ outw(REG_IE, inw(REG_IE) | INT_TMR3); /* Enable master interrupt. */ outw(REG_IME, 1); }
int NutTraceInit(int size, char mode) { if (!trace_isinit) { // start timer1 at CPU frequency/8 and register interrupt service routine outb(TCCR1B, 2); NutRegisterIrqHandler(&sig_OVERFLOW1, NutTraceTimer1IRQ, 0); sbi(TIMSK, TOIE1); trace_isinit = 1; } if (size==0) { size = TRACE_SIZE_DEFAULT; } if (size != trace_size) { // current buffer is not of size that is wanted if (trace_items != 0) { // but memory is already allocated -> free old buffer NutHeapFree(trace_items); } // allocate buffer trace_items = (t_traceitem *)NutHeapAlloc(size * sizeof(t_traceitem)); if (trace_items == 0) { // failed return trace_size = 0; } else { trace_size = size; } } // if (mode == TRACE_MODE_OFF) { // // if terminal-cmd "trace size <val>" is called trace is started in // // default mode // mode = TRACE_MODE_DEFAULT; // } trace_mode = mode; NutTraceClear(); return trace_size; }
/*! * \brief Register a GPIO pin interrupt handler. * * Generating interrupts on GPIO pin changes is not supported on all * platforms. In this case dedicated external interrupt pins may * be used with NutRegisterIrqHandler(). * * Interrupts are triggered on rising and falling edges. Level triggering * or triggering on specific edges is not supported. * * After registering, interrupts are disabled. Calling GpioIrqEnable() * is required to activate the interrupt. * * The following code fragment registers an interrupt handler which is * called on each change of bit 4 of the first GPIO port: * \code * #include <dev/gpio.h> * * static void PinChange(void *arg) * { * ... * } * * { * ... * GpioPinConfigSet(0, 4, GPIO_CFG_PULLUP); * GpioRegisterIrqHandler(&sig_GPIO, 4, PinChange, NULL); * GpioIrqEnable(&sig_GPIO, 4); * ... * } * \endcode * * \param sig Bank/port interrupt to be associated with this handler. * \param bit Bit number of the specified bank/port. * \param handler This routine will be called by Nut/OS, when the specified * pin changes its state. * \param arg Argument to be passed to the interrupt handler routine. * * \return 0 on success, -1 otherwise. */ int GpioRegisterIrqHandler(GPIO_SIGNAL * sig, int bit, void (*handler) (void *), void *arg) { int rc = 0; if (sig->ios_vector == 0) { /* This is the first call. Allocate the vector table. */ sig->ios_vector = malloc(sizeof(GPIO_VECTOR) * 32); if (sig->ios_vector) { memset(sig->ios_vector, 0, sizeof(GPIO_VECTOR) * 32); /* Register our internal PIO interrupt service. */ rc = NutRegisterIrqHandler(sig->ios_sig, sig->ios_handler, sig->ios_vector); if (rc == 0) { rc = NutIrqEnable(sig->ios_sig); } } else { rc = -1; } } sig->ios_vector[bit].iov_handler = handler; sig->ios_vector[bit].iov_arg = arg; return rc; }
/*! * \brief Initialize an SPI bus node. * * This routine is called for each SPI node, which is registered via * NutRegisterSpiDevice(). * * \param node Specifies the SPI bus node. * * \return 0 on success or -1 if there is no valid chip select. */ int At91SpiBusNodeInit(NUTSPINODE * node) { int rc; NUTSPIBUS *bus; /* Sanity check. */ NUTASSERT(node != NULL); NUTASSERT(node->node_bus != NULL); bus = node->node_bus; /* Try to deactivate the node's chip select. */ #if defined(SPI1_BASE) if (bus->bus_base == SPI1_BASE) { rc = At91Spi1ChipSelect(node->node_cs, (node->node_mode & SPI_MODE_CSHIGH) == 0); } else #endif rc = At91Spi0ChipSelect(node->node_cs, (node->node_mode & SPI_MODE_CSHIGH) == 0); /* It should not hurt us being called more than once. Thus, we ** check wether any initialization had been taken place already. */ if (rc == 0 && node->node_stat == NULL) { /* Allocate and set our shadow registers. */ AT91SPIREG *spireg = malloc(sizeof(AT91SPIREG)); if (spireg) { /* Set interface defaults. */ spireg->at91spi_mr = SPI_MODFDIS | SPI_MSTR; switch (node->node_cs) { case 0: spireg->at91spi_mr |= SPI_PCS_0; break; case 1: spireg->at91spi_mr |= SPI_PCS_1; break; case 2: spireg->at91spi_mr |= SPI_PCS_2; break; case 3: spireg->at91spi_mr |= SPI_PCS_3; break; } spireg->at91spi_csr = 0; /* Update with node's defaults. */ node->node_stat = (void *)spireg; At91SpiSetup(node); /* * Register and enable SPI interrupt handler. */ #if !defined(SPIBUS1_POLLING_MODE) && defined(SPI1_BASE) if (bus->bus_base == SPI1_BASE) { #if defined(SPIBUS1_DOUBLE_BUFFER) NutRegisterIrqHandler(bus->bus_sig, At91SpiInterrupt, &bus->bus_ready); #else NutRegisterIrqHandler(bus->bus_sig, At91SpiBus1Interrupt, &bus->bus_ready); #endif outr(bus->bus_base + SPI_IDR_OFF, (unsigned int) - 1); NutIrqEnable(bus->bus_sig); } else #endif /* !SPIBUS1_POLLING_MODE */ { #if !defined(SPIBUS0_POLLING_MODE) #if defined(SPIBUS0_DOUBLE_BUFFER) NutRegisterIrqHandler(bus->bus_sig, At91SpiInterrupt, &bus->bus_ready); #else NutRegisterIrqHandler(bus->bus_sig, At91SpiBus0Interrupt, &bus->bus_ready); #endif outr(bus->bus_base + SPI_IDR_OFF, (unsigned int) - 1); NutIrqEnable(bus->bus_sig); #endif /* !SPIBUS0_POLLING_MODE */ } } else { /* Out of memory? */ rc = -1; } } return rc; }
/*! * \brief Initialize system timer. * * This function is automatically called by Nut/OS * during system initialization. * * Nut/OS uses on-chip timer 0 for its timer services. * Applications should not modify any registers of this * timer, but make use of the Nut/OS timer API. Timer 1 * and timer 2 are available to applications. */ void NutRegisterTimer(void (*handler) (void *)) { os_handler = handler; #if defined(MCU_AT91R40008) /* Disable the Clock Counter */ outr(TC0_CCR, TC_CLKDIS); /* Disable all interrupts */ outr(TC0_IDR, 0xFFFFFFFF); /* Clear the status register. */ dummy = inr(TC0_SR); /* Select divider and compare trigger */ outr(TC0_CMR, TC_CLKS_MCK32 | TC_CPCTRG); /* Enable the Clock counter */ outr(TC0_CCR, TC_CLKEN); /* Validate the RC compare interrupt */ outr(TC0_IER, TC_CPCS); /* Disable timer 0 interrupts. */ outr(AIC_IDCR, _BV(TC0_ID)); /* Set the TC0 IRQ handler address */ outr(AIC_SVR(4), (unsigned int)Timer0Entry); /* Set the trigg and priority for timer 0 interrupt */ /* Level 7 is highest, level 0 lowest. */ outr(AIC_SMR(4), (AIC_SRCTYPE_INT_LEVEL_SENSITIVE | 0x4)); /* Clear timer 0 interrupt */ outr(AIC_ICCR, _BV(TC0_ID)); /* Enable timer 0 interrupts */ outr(AIC_IECR, _BV(TC0_ID)); /* Set compare value for 1 ms. */ outr(TC0_RC, 0x80F); /* Software trigger starts the clock. */ outr(TC0_CCR, TC_SWTRG); #elif defined(MCU_S3C4510B) INT_DISABLE(IRQ_TIMER); CSR_WRITE(TCNT0, 0); CSR_WRITE(TDATA0, CLOCK_TICK_RATE); CSR_WRITE(TMOD, TMOD_TIMER0_VAL); CLEAR_PEND_INT(IRQ_TIMER); NutRegisterIrqHandler( &InterruptHandlers[IRQ_TIMER], handler, 0); INT_ENABLE(IRQ_TIMER); #elif defined(MCU_GBA) /* Disable master interrupt. */ outw(REG_IME, 0); /* Set global interrupt vector. */ NutRegisterIrqHandler(&sig_TMR3, Timer3Entry, 0); /* Enable timer and timer interrupts. */ outdw(REG_TMR3CNT, TMR_IRQ_ENA | TMR_ENA | 48756); /* Enable timer 3 interrupts. */ outw(REG_IE, inw(REG_IE) | INT_TMR3); /* Enable master interrupt. */ outw(REG_IME, 1); #else #warning "MCU not defined" #endif }
/*! * \brief Initialize TWI interface. * * The specified slave address is not used here as we don't support twi-slave * on this architecture for now. * * \param sla Slave address, must be specified as a 7-bit address, * always lower than 128. */ int NutRegisterTwiBus( NUTTWIBUS *bus, uint8_t sla ) { int rc = -1; uint32_t speed = 80000; /* Errata Doc 14574 Rev. 9 Chapter 2.11: Avoid 88kHz to 100kHz */ // uint16_t tmpreg = 0; I2C_TypeDef* I2Cx = (I2C_TypeDef*)bus->bus_base; NUTTWIICB *icb = NULL; DBGP1_INIT(); DBGP2_INIT(); /* Check if bus was already registered */ if( bus->bus_icb) { return 0; } /* Allocate ICB for this bus */ icb = NutHeapAlloc(sizeof(NUTTWIICB)); if( icb == NULL) { return rc; } memset( icb, 0, sizeof(NUTTWIICB)); /* Link bus and ICB */ bus->bus_icb = icb; if( NutRegisterIrqHandler( bus->bus_sig_ev, TwEventIrq, bus ) ) { free( icb); return rc; } if( NutRegisterIrqHandler( bus->bus_sig_er, TwErrorIrq, bus ) ) { free( icb); return rc; } /* Initialize GPIO Hardware */ if( bus->bus_initbus != NULL) { rc = bus->bus_initbus(); } if( rc) { return rc; } /* Disable and reset this bus */ I2Cx->CR1 &= ~I2C_CR1_PE; I2Cx->CR1 |= I2C_CR1_SWRST; I2Cx->CR1 &= ~I2C_CR1_SWRST; #ifdef I2C_DEFAULT_SPEED if( bus->bus_base == I2C1_BASE) speed = I2CBUS1_DEFAULT_SPEED*1000UL; #endif #ifdef I2CBUS2_DEFAULT_SPEED if( bus->bus_base == I2C2_BASE) speed = I2CBUS2_DEFAULT_SPEED*1000UL; #endif /* Set initial rate. */ if( (rc = NutTwiSetSpeed( bus, speed))) { return rc; } /* Setup 7-Bit Addressing Mode not acknowledged */ I2Cx->OAR1 = 0x4000; /* FIXME: OAR1 Bit 14 is reserved */ #if 0 /* Setup CR1 */ tmpreg = I2Cx->CR1; tmpreg &= ~(I2C_CR1_SMBUS|I2C_CR1_SMBTYPE|I2C_CR1_PEC); tmpreg |= I2C_CR1_ACK; // TODO: Set SMBTYPE and SMBUS bits I2Cx->CR1 = tmpreg; /* Setup Interrupts */ tmpreg = I2Cx->CR2; tmpreg |= (I2C_CR2_ITBUFEN|I2C_CR2_ITEVTEN|I2C_CR2_ITERREN); I2Cx->CR2 = tmpreg; #endif I2Cx->CR1 = I2C_CR1_PE; // TODO: Slave Address Setup NutIrqSetPriority(bus->bus_sig_ev, 0); rc = NutIrqEnable(bus->bus_sig_ev); if( rc) { return rc; } NutIrqSetPriority(bus->bus_sig_er, 1); rc = NutIrqEnable(bus->bus_sig_er); if( rc) { return rc; } /* Initialize mutex semaphores. */ NutEventPost(&bus->bus_mutex); return rc; }