SPI RAM 23LC1024 (Microchip) with DMA and FIFO

Dependencies:   SerRAM mbed

Fork of SPIRAM_23LC1024_DMA by Suga koubou

main.cpp

Committer:
okini3939
Date:
2012-12-05
Revision:
2:a3e0f7f37ac9
Parent:
1:a7b1803dfa44
Child:
3:cc45604ca53f

File content as of revision 2:a3e0f7f37ac9:

/*
 * 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
#define CMD_RDMR    0x05
#define CMD_WRMR    0x01

DigitalOut myled(LED1);
Serial pc(USBTX, USBRX);

SPI spi(p11, p12, p13); // mosi, miso, sclk
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;
}

int ram_read (int addr, char *buf, int len) {
    int i;

    cs = 0;
    spi.write(CMD_READ);
    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)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;
}

int main() {
    int i;
    char buf[256];
    Timer t;

    cs = 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));
    cs = 1;
    
    printf("\r\nHELLO test\r\n");
    
    printf("RAM write\r\n");
    strcpy(buf, "Hello!");
    ram_write(0, buf, 6);
    
    for (i = 0; i < 256; i ++) {
        buf[i] = i;
    }
    ram_write(8, buf, 200);

    wait(1);
    memset(buf, 0, 256);
    
    printf("RAM read\r\n");
    ram_read(0, buf, 256);
    for (i = 0; i < 256; i ++) {
        printf(" %02x", buf[i]);
        if ((i & 0x0f) == 0x0f)
            printf("\r\n");
    }

    wait(1);

    printf("\r\nWrite/Read time\r\n");

    printf("RAM write\r\n");
    t.reset();
    t.start();
    for (i = 0; i < 0x20000; i += 256) {
        buf[0] = (i >> 8) & 0xff;
        ram_write(i, buf, 256);
        if ((i & 0x0fff) == 0) printf(".");
    }
    t.stop();
    printf("\r\ntime %f, %f KBytes/sec\r\n", t.read(), (float)0x20000 / 1024 / t.read());

    wait(1);

    printf("RAM read\r\n");
    t.reset();
    t.start();
    for (i = 0; i < 0x20000; i += 256) {
        ram_read(i, buf, 256);
        if (buf[0] != ((i >> 8) & 0xff)) {
            printf("error %d\r\n", i);
            break;
        }
        if ((i & 0x0fff) == 0) printf(".");
    }
    t.stop();
    printf("\r\ntime %f, %f KBytes/sec\r\n", t.read(), 0x20000 / 1024 / t.read());

}