static rt_err_t sd_mmc_init(rt_device_t dev) { pdca_channel_rx = pdca_get_handler(PDCA_CHANNEL_SPI_RX); pdca_channel_tx = pdca_get_handler(PDCA_CHANNEL_SPI_TX); return RT_EOK; }
uint32_t pdca_init_channel(uint8_t pdca_ch_number, const pdca_channel_options_t *opt) { /* get the correct channel pointer */ volatile avr32_pdca_channel_t *pdca_channel = pdca_get_handler( pdca_ch_number); pdca_disable_interrupt_transfer_complete(pdca_ch_number); pdca_disable_interrupt_reload_counter_zero(pdca_ch_number); irqflags_t flags = cpu_irq_save(); pdca_channel->mar = (uint32_t)opt->addr; pdca_channel->tcr = opt->size; pdca_channel->psr = opt->pid; pdca_channel->marr = (uint32_t)opt->r_addr; pdca_channel->tcrr = opt->r_size; pdca_channel->mr = #if (AVR32_PDCA_H_VERSION >= 120) opt->etrig << AVR32_PDCA_ETRIG_OFFSET | #endif opt->transfer_size << AVR32_PDCA_SIZE_OFFSET; pdca_channel->cr = AVR32_PDCA_ECLR_MASK; pdca_channel->isr; cpu_irq_restore(flags); return PDCA_SUCCESS; }
bool pdca_get_channel_status(uint8_t pdca_ch_number) { /* get the correct channel pointer */ volatile avr32_pdca_channel_t *pdca_channel = pdca_get_handler( pdca_ch_number); return (pdca_channel->sr & AVR32_PDCA_TEN_MASK) != 0; }
uint32_t pdca_get_transfer_status(uint8_t pdca_ch_number) { /* get the correct channel pointer */ volatile avr32_pdca_channel_t *pdca_channel = pdca_get_handler( pdca_ch_number); return pdca_channel->isr; }
void pdca_enable_event_trigger(uint8_t pdca_ch_number) { /* get the correct channel pointer */ volatile avr32_pdca_channel_t *pdca_channel = pdca_get_handler( pdca_ch_number); pdca_channel->mr |= AVR32_PDCA_ETRIG_MASK; }
void pdca_enable_interrupt_reload_counter_zero(uint8_t pdca_ch_number) { /* get the correct channel pointer */ volatile avr32_pdca_channel_t *pdca_channel = pdca_get_handler( pdca_ch_number); pdca_channel->ier = AVR32_PDCA_RCZ_MASK; }
void pdca_enable_interrupt_transfer_complete(uint8_t pdca_ch_number) { /* get the correct channel pointer */ volatile avr32_pdca_channel_t *pdca_channel = pdca_get_handler( pdca_ch_number); pdca_channel->ier = AVR32_PDCA_TRC_MASK; }
void pdca_set_peripheral_select(uint8_t pdca_ch_number, uint32_t pid) { /* get the correct channel pointer */ volatile avr32_pdca_channel_t *pdca_channel = pdca_get_handler( pdca_ch_number); pdca_channel->psr = pid; }
uint32_t pdca_get_reload_size(uint8_t pdca_ch_number) { /* get the correct channel pointer */ volatile avr32_pdca_channel_t *pdca_channel = pdca_get_handler( pdca_ch_number); return pdca_channel->tcrr; }
void pdca_enable(uint8_t pdca_ch_number) { /* get the correct channel pointer */ volatile avr32_pdca_channel_t *pdca_channel = pdca_get_handler( pdca_ch_number); /* Enable transfer */ pdca_channel->cr = AVR32_PDCA_TEN_MASK; }
void pdca_set_transfer_size(uint8_t pdca_ch_number, uint32_t transfer_size) { /* get the correct channel pointer */ volatile avr32_pdca_channel_t *pdca_channel = pdca_get_handler( pdca_ch_number); pdca_channel->mr = (pdca_channel->mr & ~AVR32_PDCA_SIZE_MASK) | transfer_size << AVR32_PDCA_SIZE_OFFSET; }
int media_read(unsigned long sector, unsigned char *buffer, unsigned long sector_count) { #if 1 #else unsigned long i; for (i=0;i<sector_count;i++) { pdca_load_channel( AVR32_PDCA_CHANNEL_SPI_RX, &pdcaRxBuf, FS_BUF_SIZE); pdca_load_channel( AVR32_PDCA_CHANNEL_SPI_TX, (void *)&pdcaTxBuf, FS_BUF_SIZE); //send dummy to activate the clock fsEndTransfer = false; if(sd_mmc_spi_read_open_PDCA (sector)) { spi_write(SD_MMC_SPI,0xFF); // dummy byte synchronizes transfer pdca_enable_interrupt_transfer_complete(AVR32_PDCA_CHANNEL_SPI_RX); pdcaRxChan =(volatile avr32_pdca_channel_t*) pdca_get_handler(AVR32_PDCA_CHANNEL_SPI_RX); pdcaTxChan =(volatile avr32_pdca_channel_t*) pdca_get_handler(AVR32_PDCA_CHANNEL_SPI_TX); pdcaRxChan->cr = AVR32_PDCA_TEN_MASK; // Enable RX PDCA transfer first pdcaTxChan->cr = AVR32_PDCA_TEN_MASK; // and TX PDCA transfer // wait for signal from ISR while(!fsEndTransfer) { ;; } // copy FIXME: could optimize away for(i=0; i<FS_BUF_SIZE; i++) { buffer[i] = pdcaRxBuf[i]; } } else { print_dbg("\r\n error opening PDCA at sector "); print_dbg_ulong(sector); } sector ++; buffer += FS_BUF_SIZE; } return 1; #endif }
void pdca_disable_interrupt_reload_counter_zero(uint8_t pdca_ch_number) { /* get the correct channel pointer */ volatile avr32_pdca_channel_t *pdca_channel = pdca_get_handler( pdca_ch_number); irqflags_t flags = cpu_irq_save(); pdca_channel->idr = AVR32_PDCA_RCZ_MASK; pdca_channel->isr; cpu_irq_restore(flags); }
void pdca_load_channel(uint8_t pdca_ch_number, volatile void *addr, uint32_t size) { /* get the correct channel pointer */ volatile avr32_pdca_channel_t *pdca_channel = pdca_get_handler( pdca_ch_number); irqflags_t flags = cpu_irq_save(); pdca_channel->mar = (uint32_t)addr; pdca_channel->tcr = size; pdca_channel->cr = AVR32_PDCA_ECLR_MASK; pdca_channel->isr; cpu_irq_restore(flags); }
/*! \brief Initializes SD/MMC resources: GPIO, SPI and SD/MMC. */ static void sd_mmc_resources_init(void) { // GPIO pins used for SD/MMC interface static const gpio_map_t SD_MMC_SPI_GPIO_MAP = { {SD_MMC_SPI_SCK_PIN, SD_MMC_SPI_SCK_FUNCTION }, // SPI Clock. {SD_MMC_SPI_MISO_PIN, SD_MMC_SPI_MISO_FUNCTION}, // MISO. {SD_MMC_SPI_MOSI_PIN, SD_MMC_SPI_MOSI_FUNCTION}, // MOSI. {SD_MMC_SPI_NPCS_PIN, SD_MMC_SPI_NPCS_FUNCTION} // Chip Select NPCS. }; // SPI options. spi_options_t spiOptions = { .reg = SD_MMC_SPI_NPCS, .baudrate = SD_MMC_SPI_MASTER_SPEED, // Defined in conf_sd_mmc_spi.h. .bits = SD_MMC_SPI_BITS, // Defined in conf_sd_mmc_spi.h. .spck_delay = 0, .trans_delay = 0, .stay_act = 1, .spi_mode = 0, .modfdis = 1 }; // Assign I/Os to SPI. gpio_enable_module(SD_MMC_SPI_GPIO_MAP, sizeof(SD_MMC_SPI_GPIO_MAP) / sizeof(SD_MMC_SPI_GPIO_MAP[0])); // Initialize as master. spi_initMaster(SD_MMC_SPI, &spiOptions); // Set SPI selection mode: variable_ps, pcs_decode, delay. spi_selectionMode(SD_MMC_SPI, 0, 0, 0); // Enable SPI module. spi_enable(SD_MMC_SPI); // Initialize SD/MMC driver with SPI clock (PBA). sd_mmc_spi_init(spiOptions, PBA_HZ); } /*! \brief Initialize PDCA (Peripheral DMA Controller A) resources for the SPI transfer and start a dummy transfer */ void local_pdca_init(void) { // this PDCA channel is used for data reception from the SPI pdca_channel_options_t pdca_options_SPI_RX ={ // pdca channel options .addr = ram_buffer, // memory address. We take here the address of the string dummy_data. This string is located in the file dummy.h .size = 512, // transfer counter: here the size of the string .r_addr = NULL, // next memory address after 1st transfer complete .r_size = 0, // next transfer counter not used here .pid = AVR32_PDCA_CHANNEL_USED_RX, // select peripheral ID - data are on reception from SPI1 RX line .transfer_size = PDCA_TRANSFER_SIZE_BYTE // select size of the transfer: 8,16,32 bits }; // this channel is used to activate the clock of the SPI by sending a dummy variables pdca_channel_options_t pdca_options_SPI_TX ={ // pdca channel options .addr = (void *)&dummy_data, // memory address. // We take here the address of the string dummy_data. // This string is located in the file dummy.h .size = 512, // transfer counter: here the size of the string .r_addr = NULL, // next memory address after 1st transfer complete .r_size = 0, // next transfer counter not used here .pid = AVR32_PDCA_CHANNEL_USED_TX, // select peripheral ID - data are on reception from SPI1 RX line .transfer_size = PDCA_TRANSFER_SIZE_BYTE // select size of the transfer: 8,16,32 bits }; // Init PDCA transmission channel pdca_init_channel(AVR32_PDCA_CHANNEL_SPI_TX, &pdca_options_SPI_TX); // Init PDCA Reception channel pdca_init_channel(AVR32_PDCA_CHANNEL_SPI_RX, &pdca_options_SPI_RX); //! \brief Enable pdca transfer interrupt when completed INTC_register_interrupt(&pdca_int_handler, AVR32_PDCA_IRQ_0, AVR32_INTC_INT1); // pdca_channel_spi1_RX = 0 } /*! \brief Main function. Execution starts here. */ int main(void) { int i, j; // Switch the main clock to the external oscillator 0 pcl_switch_to_osc(PCL_OSC0, FOSC0, OSC0_STARTUP); // Initialize debug RS232 with PBA clock init_dbg_rs232(PBA_HZ); //start test print_dbg("\r\nInit SD/MMC Driver"); print_dbg("\r\nInsert SD/MMC..."); // Initialize Interrupt Controller INTC_init_interrupts(); // Initialize SD/MMC driver resources: GPIO, SPI and SD/MMC. sd_mmc_resources_init(); // Wait for a card to be inserted while (!sd_mmc_spi_mem_check()); print_dbg("\r\nCard detected!"); // Read Card capacity sd_mmc_spi_get_capacity(); print_dbg("Capacity = "); print_dbg_ulong(capacity >> 20); print_dbg(" MBytes"); // Enable all interrupts. Enable_global_interrupt(); // Initialize PDCA controller before starting a transfer local_pdca_init(); // Read the first sectors number 1, 2, 3 of the card for(j = 1; j <= 3; j++) { // Configure the PDCA channel: the address of memory ram_buffer to receive the data at sector address j pdca_load_channel( AVR32_PDCA_CHANNEL_SPI_RX, &ram_buffer, 512); pdca_load_channel( AVR32_PDCA_CHANNEL_SPI_TX, (void *)&dummy_data, 512); //send dummy to activate the clock end_of_transfer = false; // open sector number j if(sd_mmc_spi_read_open_PDCA (j)) { print_dbg("\r\nFirst 512 Bytes of Transfer number "); print_dbg_ulong(j); print_dbg(" :\r\n"); spi_write(SD_MMC_SPI,0xFF); // Write a first dummy data to synchronize transfer pdca_enable_interrupt_transfer_complete(AVR32_PDCA_CHANNEL_SPI_RX); pdca_channelrx =(volatile avr32_pdca_channel_t*) pdca_get_handler(AVR32_PDCA_CHANNEL_SPI_RX); // get the correct PDCA channel pointer pdca_channeltx =(volatile avr32_pdca_channel_t*) pdca_get_handler(AVR32_PDCA_CHANNEL_SPI_TX); // get the correct PDCA channel pointer pdca_channelrx->cr = AVR32_PDCA_TEN_MASK; // Enable RX PDCA transfer first pdca_channeltx->cr = AVR32_PDCA_TEN_MASK; // and TX PDCA transfer while(!end_of_transfer); // Display the first 2O bytes of the ram_buffer content for( i = 0; i < 20; i++) { print_dbg_char_hex( (U8)(*(ram_buffer + i))); } } else { print_dbg("\r\n! Unable to open memory \r\n"); } } print_dbg("\r\nEnd of the example.\r\n"); while (1); }
/** ** 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 } }