Hallo zusammen,
ich lese einen ADC über SPI aus. Klappt soweit auch alles. Nun möchte ich die empfagenen Daten direkt im SDRAM ablegen. Dies soll über DMA gehen, damit der UC3C nicht unnötig belastet wird (AT32UC3C-ek Board).
Es werden 16 Bit auf einmal ausgelesen und es sollen dann auch 16 Bit an den SDRAM übertragen werden. Sieht jemand einen generellen Fehler beim initialisiren des DMA?
ich lese einen ADC über SPI aus. Klappt soweit auch alles. Nun möchte ich die empfagenen Daten direkt im SDRAM ablegen. Dies soll über DMA gehen, damit der UC3C nicht unnötig belastet wird (AT32UC3C-ek Board).
Es werden 16 Bit auf einmal ausgelesen und es sollen dann auch 16 Bit an den SDRAM übertragen werden. Sieht jemand einen generellen Fehler beim initialisiren des DMA?
Code:
#include <asf.h>
#include "board.h"
#include "gpio.h"
#include "power_clocks_lib.h"
#include "cycle_counter.h"
#include "delay.h"
#include "sdramc.h"
#include "pdca.h"
#include <sysclk.h>
#include <intc.h>
#include <flashc.h>
#include <compiler.h>
#define DUMMY_TO_SEND 0x1C1C
#define PDCA_0_SPI_RX 0 // In the example we will use the pdca channel 0.
#define PDCA_0_SPI_TX 1 // In the example we will use the pdca channel 1.
// PDCA Channel pointer
volatile avr32_pdca_channel_t* pdca_channelrx ;
volatile avr32_pdca_channel_t* pdca_channeltx ;
#define PBC 12000000
#define SPI_TMP (&AVR32_SPI0)
#define LED AVR32_PIN_PD23
#define ADC_READY AVR32_PIN_PB08
#define SWITCH AVR32_PIN_PA14
uint16_t dummy[1];
unsigned long sdram_size;
volatile unsigned long *sdram = SDRAM;
char data_array[14];
volatile uint16_t isr_data1, isr_data2;
#if defined (__GNUC__)
__attribute__((__interrupt__))
#elif defined (__ICCAVR32__)
__interrupt
#endif
static void pdca_int_handler(void)
{
}
__attribute__((__interrupt__))
static void int_handler_adc(void){
if(gpio_get_pin_interrupt_flag(ADC_READY)){
//read a channel
spi_write(SPI_TMP, DUMMY_TO_SEND);
spi_read(SPI_TMP, &isr_data1);
spi_write(SPI_TMP, DUMMY_TO_SEND);
spi_read(SPI_TMP, &isr_data2);
//clear interrupt flag
gpio_clear_pin_interrupt_flag(ADC_READY);
}
}
void init_ram(void){
// Calculate SDRAM size in words (32 bits).
sdram_size = SDRAM_SIZE >> 2;
// Initialize the external SDRAM chip.
sdramc_init(FOSC0);
}
//init spi 0
void init_spi(void){
//map gpio pins
static const gpio_map_t SPI_GPIO_MAPPING =
{
{AVR32_SPI0_SCK_0_2_PIN, AVR32_SPI0_SCK_0_2_FUNCTION }, // SPI Clock. J 33.6
{AVR32_SPI0_MISO_0_2_PIN, AVR32_SPI0_MISO_0_2_FUNCTION}, // MISO. J 33.3
{AVR32_SPI0_MOSI_0_2_PIN, AVR32_SPI0_MOSI_0_2_FUNCTION}, // MOSI. J 33.4
{AVR32_SPI0_NPCS_0_2_PIN, AVR32_SPI0_NPCS_0_2_FUNCTION} // Chip Select NPCS J 33.5
};
// Assign I/Os to SPI
gpio_enable_module(SPI_GPIO_MAPPING, sizeof(SPI_GPIO_MAPPING) / sizeof(SPI_GPIO_MAPPING[0]));
//enable the clock for the spi controller
sysclk_enable_pba_module(SYSCLK_SPI0);
//set spi options
spi_options_t spi_options =
{
.baudrate = 12000000, // spi baudrate
.bits = 16, // number of bits from 8 to 16
.modfdis = 0, // disables the mode fault detection
.reg = 0, // spi channel
.spck_delay = 0, // delay before first clock pulse
.spi_mode = 1, // spi mode to use when transmitting
.stay_act = 0, // sets this chip to stay active after last transfer
.trans_delay = 0 // delay between each transfer
};
spi_initMaster(SPI_TMP, &spi_options); // init function
spi_set_master_mode(SPI_TMP); // set master mode
spi_selectChip(SPI_TMP, 0); // select a chip
spi_setupChipReg(SPI_TMP, &spi_options, PBC); // setup chip
spi_enable(SPI_TMP); // enable spi
}
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 = sdram, // memory address
.size = sdram_size, // transfer counter: here the size of the sdram
.r_addr = NULL, // next memory address after 1st transfer complete
.r_size = 0, // next transfer counter not used here
.pid = AVR32_PDCA_PID_SPI0_RX, // select peripheral ID - data are on reception from SPI0 RX line
.transfer_size = PDCA_TRANSFER_SIZE_HALF_WORD // select size of the transfer: 16 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, // memory address.
.size = 16, // transfer counter: here the size of the dummy
.r_addr = NULL, // next memory address after 1st transfer complete
.r_size = 0, // next transfer counter not used here
.pid = AVR32_PDCA_PID_SPI0_TX, // select peripheral ID - data are on reception from SPI0 RX line
.transfer_size = PDCA_TRANSFER_SIZE_HALF_WORD // select size of the transfer: 16 bits
};
// Init PDCA transmission channel
pdca_init_channel(PDCA_0_SPI_TX, &pdca_options_SPI_TX);
// Init PDCA Reception channel
pdca_init_channel(PDCA_0_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);
}
int main (void){
//Switch the main clock to the external oscillator 0
pcl_switch_to_osc(PCL_OSC0, FOSC0, OSC0_STARTUP);
dummy[0] = 0x1111;
//init functions
init_ram();
init_spi();
INTC_init_interrupts();
Disable_global_interrupt();
//ADC_READY pin as interrupt
gpio_enable_pin_interrupt(ADC_READY , GPIO_FALLING_EDGE);
INTC_register_interrupt(&int_handler_adc, AVR32_GPIO_IRQ_0 + (ADC_READY/8), AVR32_INTC_INT0);
Enable_global_interrupt();
local_pdca_init();
pdca_load_channel( PDCA_0_SPI_TX, (void *)&dummy, 16); //send dummy to activate the clock
pdca_load_channel(PDCA_0_SPI_RX, sdram, 16);
// get the correct PDCA channel pointer
pdca_channelrx =(volatile avr32_pdca_channel_t*) pdca_get_handler(PDCA_0_SPI_RX);
// get the correct PDCA channel pointer
pdca_channeltx =(volatile avr32_pdca_channel_t*) pdca_get_handler(PDCA_0_SPI_TX);
// Enable RX PDCA transfer first
pdca_channelrx->cr = AVR32_PDCA_TEN_MASK;
pdca_channeltx->cr = AVR32_PDCA_TEN_MASK;
while(1){
;
}
return 0;
}