Spi->dma-sdram

mister-g

Neues Mitglied
04. Sep. 2011
2
0
0
39
Sprachen
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?

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;
}
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)