SPI RAM 23LC1024 (Microchip) with DMA

Dependencies:   mbed

Fork of SPIRAM_23LC1024 by Suga koubou

Revision:
2:a3e0f7f37ac9
Parent:
1:a7b1803dfa44
--- a/main.cpp	Fri Nov 09 06:23:54 2012 +0000
+++ b/main.cpp	Wed Dec 05 07:56:09 2012 +0000
@@ -1,8 +1,12 @@
 /*
  * SPI RAM 23LC1024 (Microchip)
  *   1Mbit
+ *   with DMA ( http://mbed.org/users/AjK/code/MODDMA/ )
  */
 #include "mbed.h"
+#include "MODDMA.h"
+
+#define ENABLE_DMA
 
 #define CMD_READ    0x03
 #define CMD_WRITE   0x02
@@ -13,20 +17,96 @@
 Serial pc(USBTX, USBRX);
 
 SPI spi(p11, p12, p13); // mosi, miso, sclk
-DigitalOut cs(p17), hold(p18);
+DigitalOut cs(p14);
+
+MODDMA dma;
+MODDMA_Config *dmacfg0 = NULL, *dmacfg1 = NULL;
+DigitalOut led2(LED2), led3(LED3), led4(LED4);
+volatile int dmaexit;
+
+extern "C" void HardFault_Handler() {
+    register unsigned int _msp __asm("msp");
+    printf("Hard Fault! address: %08x\r\n", *((unsigned int *)(_msp + 24)));
+    exit(-1);
+}  
+
+void tc0_callback () {
+    led2 = 1;
+    
+    MODDMA_Config *config = dma.getConfig();
+    dma.Disable( (MODDMA::CHANNELS)config->channelNum() );
+
+    // Clear DMA IRQ flags.
+    if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq();    
+    if (dma.irqType() == MODDMA::ErrIrq) dma.clearErrIrq();    
+}
+
+void tc1_callback () {
+    dmaexit = 1;
+    led3 = 1;
+    
+    MODDMA_Config *config = dma.getConfig();
+    dma.Disable( (MODDMA::CHANNELS)config->channelNum() );
+
+    // Clear DMA IRQ flags.
+    if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq();    
+    if (dma.irqType() == MODDMA::ErrIrq) dma.clearErrIrq();    
+}
+
+void err_callback () {
+    dmaexit = 1;
+    led4 = 1;
+    printf("err\r\n");
+}
 
 int ram_write (int addr, char *buf, int len) {
     int i;
+    char dummy[len];
 
     cs = 0;
     spi.write(CMD_WRITE);
     spi.write((addr >> 16) & 0xff);
     spi.write((addr >> 8) & 0xff);
     spi.write(addr & 0xff);
+    
+#ifdef ENABLE_DMA
+    dmacfg0
+     ->channelNum    ( MODDMA::Channel_0 )
+     ->srcMemAddr    ( (uint32_t)buf )
+     ->dstMemAddr    ( MODDMA::SSP0_Tx )
+     ->transferSize  ( len )
+     ->transferType  ( MODDMA::m2p )
+     ->dstConn       ( MODDMA::SSP0_Tx )
+     ->attach_tc     ( &tc0_callback )
+     ->attach_err    ( &err_callback )
+    ; // config end
 
+    dmacfg1
+     ->channelNum    ( MODDMA::Channel_1 )
+     ->srcMemAddr    ( MODDMA::SSP0_Rx )
+     ->dstMemAddr    ( (uint32_t)dummy )
+     ->transferSize  ( len )
+     ->transferType  ( MODDMA::p2m )
+     ->srcConn       ( MODDMA::SSP0_Rx )
+     ->attach_tc     ( &tc1_callback )
+     ->attach_err    ( &err_callback )
+    ; // config end
+    
+    if (dma.Setup( dmacfg0 ) && dma.Setup( dmacfg1 )) {
+        dmaexit = 0;
+        LPC_SSP0->DMACR = (1<<1)|(1<<0); // TX,RXDMAE
+        dma.Enable( dmacfg0 );
+        dma.Enable( dmacfg1 );
+        while (! dmaexit);
+    } else {
+        printf("error\r\n");
+    }
+    LPC_SSP0->DMACR = 0;
+#else
     for (i = 0; i < len; i ++) {
         spi.write(buf[i]);
     }
+#endif
     cs = 1;
     return i;
 }
@@ -40,9 +120,44 @@
     spi.write((addr >> 8) & 0xff);
     spi.write(addr & 0xff);
 
+#ifdef ENABLE_DMA
+    dmacfg0
+     ->channelNum    ( MODDMA::Channel_0 )
+     ->srcMemAddr    ( (uint32_t)buf )
+     ->dstMemAddr    ( MODDMA::SSP0_Tx )
+     ->transferSize  ( len )
+     ->transferType  ( MODDMA::m2p )
+     ->dstConn       ( MODDMA::SSP0_Tx )
+     ->attach_tc     ( &tc0_callback )
+     ->attach_err    ( &err_callback )
+    ; // config end
+
+    dmacfg1
+     ->channelNum    ( MODDMA::Channel_1 )
+     ->srcMemAddr    ( MODDMA::SSP0_Rx )
+     ->dstMemAddr    ( (uint32_t)buf )
+     ->transferSize  ( len )
+     ->transferType  ( MODDMA::p2m )
+     ->srcConn       ( MODDMA::SSP0_Rx )
+     ->attach_tc     ( &tc1_callback )
+     ->attach_err    ( &err_callback )
+    ; // config end
+    
+    if (dma.Setup( dmacfg0 ) && dma.Setup( dmacfg1 )) {
+        dmaexit = 0;
+        LPC_SSP0->DMACR = (1<<1)|(1<<0); // TX,RXDMAE
+        dma.Enable( dmacfg0 );
+        dma.Enable( dmacfg1 );
+        while (! dmaexit);
+    } else {
+        printf("error\r\n");
+    }
+    LPC_SSP0->DMACR = 0;
+#else
     for (i = 0; i < len; i ++) {
         buf[i] = spi.write(0);
     }
+#endif
     cs = 1;
     return i;
 }
@@ -53,11 +168,14 @@
     Timer t;
 
     cs = 1;
-    hold = 1;
+#ifdef ENABLE_DMA
+    dmacfg0 = new MODDMA_Config;
+    dmacfg1 = new MODDMA_Config;
+#endif
     pc.baud(115200);
     spi.frequency(16000000);
     wait_ms(500);
-    
+
     cs = 0;
     spi.write(CMD_RDMR);
     printf("RAM mode: %02x\r\n", spi.write(0));
@@ -72,7 +190,7 @@
     for (i = 0; i < 256; i ++) {
         buf[i] = i;
     }
-    ram_write(6, buf, 256);
+    ram_write(8, buf, 200);
 
     wait(1);
     memset(buf, 0, 256);