Gast
#740329
Hallo Forum,
experimentiere seit einigen Tagen mit der DMA des TMS470 und dessen SPI.
Ich möchte eine Datenübertragung aus dem internen RAM (ca. 30000 Bytes)
an die SPI über die DMA realisieren, wobei die SPI nur als Master
verwendet werden soll und nur Daten in Byte-Form senden soll. Über den
Enable-Pin der SPI soll der SPI-Datenstrom angehalten werden
können(jedoch nicht generell abgebrochen) und somit der DMA-Transfer
angehalten werden. Ist der DMA-Counter auf Null, soll ein Interrupt
ausgelöst werden, in dessen Routine die DMA wieder neu initialisiert
werden soll und weiter arbeitet.
Anbei einige Code-Fragmente:
[1.] DMA-Initialisierung:
void InitDMA_STA013(void)
{
DMAS = 0;
DMAC = rDMAC;
DMASA = (unsigned int)&buffer[0];
DMADA = 0xFFF7F80C;
DMATC = 30000;
DMACC0 = 0x00000a00;
DMAGC = 0x00000000;
DMAGD = 0x00000000;
}
mit
//DMA config reg
#define NCPACK (0x00 << 24) // next packet
#define INTEN (1 << 15) // interrupt after compleate
#define TRSIZE (0 << 13) // transfer access size
#define DSTINC (0 << 11) // dest address increment
#define SRCINC (1 << 9) // source address increment
#define DSTMOD (0xF << 5) // dest module
#define SRCMOD (0x1 << 1) // source module
#define DCHN (1 << 0) // Data chaining enable
#define rDMAC (0x00000000 | NCPACK | INTEN | TRSIZE | DSTINC | SRCINC |
DSTMOD | SRCMOD | DCHN)
[2.] in der Interrupt-Routine:
void irq_handler(void)
{
switch ((0xFF & IRQIVEC) - 1)
{
case DMA_1_INT: // INT 28
InitDMA_STA013();
DMACPS = 0x00000001; //update for transfer
DMACCP0 = DMA_EN2; //enable the DMA to transfer
libarm_enable_irq();
break;
}
}
[3.] SPI-Initialisierung
//--- initialisiere STA013 SPI-Bus ---
void InitSPI(void)
{
unsigned char data;
int i,j;
//--- init the SPI1 bus for STA013 ---
SPI1CTRL1= (8 << SPI1CTRL1_LPDOUT_BIT) |// 8 bit tief
(1 << SPI1CTRL1_RXDOUT_BIT); // Vorteiler = 1
SPI1CTRL2 = SPI1CTRL2_MASTER + // MasterMode
SPI1CTRL2_CLKMOD + // Master Mode
SPI1CTRL2_POLARITY; // Polarity FLAG gesetzt
SPI1CTRL3 = 0x10; // DMA-Req-En, SPI1 Int
SPI1PC6 = SPI1PC6_SOMIFUN +
SPI1PC6_SIMOIFUN +
SPI1PC6_CLKFUN +
SPI1PC6_ENAFUN; // SOMI SIMO SPICLK ENA
SPI1PC1 = //SPI1PC1_ENADIR + // EN-Pin ist GPIO
SPI1PC1_SCSDIR; // CS-Pin is output for GIOP
SPI1CTRL2 |= SPI1CTRL2_SPIEN; // Enable SPIs
data = SPI1BUF; // Dummy Read to clear buffer
}
[4.] in der MAIN-Routine
int main(void)
{
//--- initialisiere Peripherie --
InitPorts();
InitInterrupts();
InitSPI();
InitDMA_STA013(); // setup DMA and enable it
__ARMLIB_enableIRQ();
DMACPS = 0x00000001; //update for transfer
DMACCP0 = DMA_EN2; //enable the DMA to transfer
while(1){
asm("nop");
};
}
So sollte die DMA ständig den Pufferinhalt über SPI raussenden. Wird der
Enable-Pin auf LOW gezogen, stoppt der Transfer, solange er auf LOW
bleibt. In der Interrup-Routine wird die DMA nachgeladen und neu
gestartet.
Es ergaben sich nun folgende Probleme:
(a) Setze ich in der Interrupt-Routine einen Breakpoint, hält der
Debugger auch ordentlich an, lasse ich das Programm über RUN
weiterlaufen, wird die ISR nie wieder aufgerufen; stattdessen lande ich
irgendwo in der Initialisierungsroutine "InitPorts()".
(b) Lasse ich den Enable der Interrupts in der ISR weg, wird die ISR nur
einmal durchlaufen - danach scheint kein weiterer DMA-Transfer
durchgeführt zu werden.
(c) Setze ich en Enable-Pin mehrmals auf LOW und wieder auf HIGH, kann
es vorkommen, dass das gleiche Ergebnis wie bei (a) entsteht. Nach einem
Reset der CPU und programmstart, ergibt sich keine weitere DMA-Funktion;
erst wenn ich die Spannung vom Prozessor nehme sowie den OLIMEX abklemme
und anschließend alles wieder einschalte, kann ich wieder einen
DMA-Zyklus laufen.
Ich habe mir das Datasheet derDMA des TMS470 sowie SPNA105 angesehen;
die Beispiele scheinen jedoch nicht wirklich zu laufen. Hat jemand eine
Idee oder ein funktionierendes Beispiel für DMA->SPI ???
Ich wäre sehr dankbar,
Michael.
Ich verwende den TMS470R1B1M und für die Entwicklung CrossWorks von
Rowley V1.6 Built 2 sowie den JTAG Dongle von OLIMEX. Das Board ist ein
Eigenbau, der in zahlreichen anderen (nicht-DMA-Projekten) tadellos
funktioniert. Die SPI funktioniert ebenfalls (ohne DNA) einwandfrei.