/** ** PDCA Init. **/ void init_pdca(void) { // PDCA channel 0/1 options static const pdca_channel_options_t PDCA_CH_OPTIONS = { .addr = (void *)aDataTransfered, // memory address .pid = AVR32_PDCA_PID_USART2_TX, // select peripheral - data are transmit on USART TX line. .size = 0, // transfer counter .r_addr = (void *)aDataTransfered, // next memory address .r_size = sizeof(aDataTransfered), // next transfer counter .transfer_size = PDCA_TRANSFER_SIZE_BYTE, // select size of one data packet .etrig = true // Trigger transfer on event. }; Disable_global_interrupt(); // Initialize interrupt vectors. INTC_init_interrupts(); // Register the PDCA interrupt handler to the interrupt controller. INTC_register_interrupt(&pdca_int_handler, PDCA_CHANNEL_IRQ, AVR32_INTC_INT0); Enable_global_interrupt(); // Init PDCA channel with the pdca_options. pdca_init_channel(PDCA_CHANNEL_USART, &PDCA_CH_OPTIONS); pdca_channel = pdca_get_handler(PDCA_CHANNEL_USART); // For use in the pdca interrupt handler. // Enable pdca transfer error interrupt & transfer complete interrupt. pdca_enable_interrupt_transfer_error(PDCA_CHANNEL_USART); pdca_enable_interrupt_transfer_complete(PDCA_CHANNEL_USART); // Enable the PEVC channel "PDCA CHANNEL 0/1 ONE-ITEM-TRANSFER" PEVC_CHANNELS_ENABLE(ppevc, 1<<PEVC_PDCA_SOT_USER); // Enable the PDCA. pdca_enable(PDCA_CHANNEL_USART); } /** ** AST Init. **/ void init_ast(void) { avr32_ast_pir0_t pir = { .insel = 14 // Set a event every second }; ast_calendar_t ast_calendar; ast_calendar.FIELD.sec = 30; ast_calendar.FIELD.min = 45; ast_calendar.FIELD.hour = 12; ast_calendar.FIELD.day = 7; ast_calendar.FIELD.month= 10; ast_calendar.FIELD.year = 9; scif_osc32_opt_t opt; opt.mode = SCIF_OSC_MODE_2PIN_CRYSTAL; opt.startup = AVR32_SCIF_OSCCTRL32_STARTUP_0_RCOSC; // Start OSC_32KHZ scif_start_osc32(&opt,true); // Initialize the AST if (!ast_init_calendar(&AVR32_AST, AST_OSC_32KHZ, AST_PSEL_32KHZ_1HZ, ast_calendar)) { print_dbg("Error initializing the AST\r\n"); while(1); } ast_set_periodic0_value(&AVR32_AST,pir); ast_enable_periodic0(&AVR32_AST); // Clear All Interrupt AVR32_AST.scr=0xFFFFFFFF; // Enable the AST ast_enable(&AVR32_AST); } /*! \brief Initializes the MCU system clocks. */ static void init_sys_clocks(void) { /*! \name System Clock Frequencies */ //! @{ static pcl_freq_param_t pcl_freq_param = { .cpu_f = FCPU_HZ, .pba_f = FPBA_HZ, .osc0_f = FOSC0, .osc0_startup = OSC0_STARTUP }; //! @} // Configure system clocks. if (pcl_configure_clocks(&pcl_freq_param) != PASS) { while(1); } } /*! \brief This example show a DMA transfer to USART controlled by the AST periodic alarm using the PEVC. */ int main(void) { int i; // Init the string with a simple recognizable pattern. for(i=0;i<sizeof(aDataTransfered);i++) aDataTransfered[i] = '0' + (i%36); init_sys_clocks(); init_usart(); gpio_clr_gpio_pin(LED0_GPIO); init_pevc(); init_ast(); init_pdca(); while(1) { gpio_tgl_gpio_pin(LED1_GPIO); delay_ms(500); //Wait 500ms } }
int8_t i2c_driver_trigger_request(uint8_t i2c_device, uint8_t schedule_slot) { // initiate transfer of given request // set up DMA channel volatile avr32_twim_t *twim; i2c_packet_conf_t* conf = &schedule[i2c_device][schedule_slot].config; static pdca_channel_options_t PDCA_OPTIONS = { .addr = 0, // memory address .pid = AVR32_TWIM0_PDCA_ID_TX, // select peripheral .size = 4, // transfer counter .r_addr = NULL, // next memory address .r_size = 0, // next transfer counter .transfer_size = PDCA_TRANSFER_SIZE_BYTE // select size of the transfer }; switch (i2c_device) { case 0: twim = &AVR32_TWIM0; twim->cr = AVR32_TWIM_CR_MEN_MASK; twim->cr = AVR32_TWIM_CR_SWRST_MASK; twim->cr = AVR32_TWIM_CR_MDIS_MASK; switch (conf->direction) { case I2C_WRITE1_THEN_READ: case I2C_READ: PDCA_OPTIONS.pid = AVR32_TWIM0_PDCA_ID_RX; PDCA_OPTIONS.addr = (void *)conf->read_data; PDCA_OPTIONS.size=conf->read_count; // Init PDCA channel with the pdca_options. pdca_init_channel(TWI0_DMA_CH, &PDCA_OPTIONS); // init PDCA channel with options. break; case I2C_WRITE: PDCA_OPTIONS.pid = AVR32_TWIM0_PDCA_ID_TX; PDCA_OPTIONS.addr = (void *)conf->write_data; PDCA_OPTIONS.size=conf->write_count; // Init PDCA channel with the pdca_options. pdca_init_channel(TWI0_DMA_CH, &PDCA_OPTIONS); // init PDCA channel with options. pdca_load_channel(TWI0_DMA_CH, (void *)conf->write_data, conf->write_count); break; } //pdca_load_channel(TWI0_DMA_CH, (void *)schedule[i2c_device][schedule_slot].config.write_data, schedule[i2c_device][schedule_slot].config.write_count); // Enable pdca interrupt each time the reload counter reaches zero, i.e. each time // the whole block was received pdca_enable_interrupt_transfer_complete(TWI0_DMA_CH); pdca_enable_interrupt_transfer_error(TWI0_DMA_CH); break; case 1: twim = &AVR32_TWIM1; break; default: // invalid device ID return -1; } // set up I2C speed and mode //twim_set_speed(twim, 100000, sysclk_get_pba_hz()); switch (conf->direction) { case I2C_READ: twim->cmdr = (conf->slave_address << AVR32_TWIM_CMDR_SADR_OFFSET) | (conf->read_count << AVR32_TWIM_CMDR_NBYTES_OFFSET) | (AVR32_TWIM_CMDR_VALID_MASK) | (AVR32_TWIM_CMDR_START_MASK) | (0 << AVR32_TWIM_CMDR_STOP_OFFSET) | (0 << AVR32_TWIM_CMDR_READ_OFFSET); break; case I2C_WRITE1_THEN_READ: print_util_dbg_print( "wr"); // set up next command register for the burst read transfer // set up command register to initiate the write transfer. The DMA will take care of the reading once this is done. twim->cmdr = (conf->slave_address << AVR32_TWIM_CMDR_SADR_OFFSET) | (1 << AVR32_TWIM_CMDR_NBYTES_OFFSET) | (AVR32_TWIM_CMDR_VALID_MASK) | (AVR32_TWIM_CMDR_START_MASK) | (0 << AVR32_TWIM_CMDR_STOP_OFFSET) ; twim->ncmdr = (conf->slave_address << AVR32_TWIM_CMDR_SADR_OFFSET) | ((conf->read_count) << AVR32_TWIM_CMDR_NBYTES_OFFSET) | (AVR32_TWIM_CMDR_VALID_MASK) | (AVR32_TWIM_CMDR_START_MASK) | (0 << AVR32_TWIM_CMDR_STOP_OFFSET) | (0 << AVR32_TWIM_CMDR_READ_OFFSET); // set up writing of one byte (usually a slave register index) //twim->cr = AVR32_TWIM_CR_MEN_MASK; twim->thr = conf->write_then_read_preamble; twim->cr = AVR32_TWIM_CR_MEN_MASK; break; case I2C_WRITE: print_util_dbg_print( "w"); twim->cmdr = (conf->slave_address << AVR32_TWIM_CMDR_SADR_OFFSET) | ((conf->write_count) << AVR32_TWIM_CMDR_NBYTES_OFFSET) | (AVR32_TWIM_CMDR_VALID_MASK) | (AVR32_TWIM_CMDR_START_MASK) | (0 << AVR32_TWIM_CMDR_STOP_OFFSET) ; twim->ncmdr = (conf->slave_address << AVR32_TWIM_CMDR_SADR_OFFSET) | ((conf->write_count) << AVR32_TWIM_CMDR_NBYTES_OFFSET) //| (AVR32_TWIM_CMDR_VALID_MASK) | (AVR32_TWIM_CMDR_START_MASK) | (0 << AVR32_TWIM_CMDR_STOP_OFFSET) ; break; } // start transfer current_schedule_slot[i2c_device] = schedule_slot; schedule[i2c_device][schedule_slot].transfer_in_progress = 1; twim->cr = AVR32_TWIM_CR_MEN_MASK; pdca_enable(TWI0_DMA_CH); return 0; } int8_t i2c_driver_pause_request(uint8_t i2c_device, uint8_t schedule_slot) { // pause scheduler // if this request currently active, wait for current transfer to finish // deactivate request // resume scheduler } int8_t i2c_driver_enable_request(uint8_t i2c_device, uint8_t schedule_slot){ return 0; } int8_t i2c_driver_remove_request(uint8_t i2c_device, uint8_t schedule_slot){ return 0; }