dmac_sample.c

来自「最新版IAR FOR ARM(EWARM)5.11中的代码例子」· C语言 代码 · 共 283 行

C
283
字号
/*************************************************************************************/
/*                                                                                   */
/*      Copyright (C) 2005 Oki Electric Industry Co., LTD.                           */
/*                                                                                   */
/*      System Name     :  ML674051/ML674061 series                                  */
/*      Module Name     :  DMAC Sample Functions                                     */
/*      File   Name     :  dmac_sample.c                                             */
/*      Revision        :  1.00                                                      */
/*      Date            :  2005/02/18                                                */
/*                                                                                   */
/*************************************************************************************/
#include "ML674061.h"
#include "common.h"
#include "irq.h"

#ifdef __IAR__
#include "intrinsics.h"
#endif

/* DMAC channel base address */
#define DMAC_BASE0          0x7BE00100  /* DMAC CH0 base address */
#define DMAC_BASE1          0x7BE00200  /* DMAC CH1 base address */

/* DMAC channel registers (offset) */
#define MSK      0x0000     /* channel mask register */
#define TMOD     0x0004     /* transmit mode register */
#define SAD      0x0008     /* source data address register */
#define DAD      0x000c     /* destination data address register */
#define SIZ      0x0010     /* transmit size register */
#define CINT     0x0014     /* clear interrupt register */

/* setting channel */
#define CH0_MODE            0x003b  /* auto request, 16 bit transmission,
                                       source data type(incremental address device),
                                       destination data type(incremental address device),
                                       cycle steal mode,
                                       interrupt mask clear */
#define CH1_MODE            0x001b  /* auto request, 16 bit transmission,
                                       source data type(incremental address device),
                                       destination data type(incremental address device),
                                       burst mode,
                                       interrupt mask clear */
static HWORD	ch0_dest_buffer[2048] ;
static HWORD	ch1_dest_buffer[2048] ;


/* transmit start address */
#define CH0_S_START_ADD     0x08000000  	 /* source data start address CH0 */
#define CH0_D_START_ADD     ch0_dest_buffer  /* destination data start address CH0 */
#define CH1_S_START_ADD     0x08001000  	 /* source data start address CH1 */
#define CH1_D_START_ADD     ch1_dest_buffer  /* destination data start address CH1 */

/* the number of times of transmission */
#define NUM_OF_TIME_CH0     2048   /* the number of times of transmission CH0 */
#define NUM_OF_TIME_CH1     2048   /* the number of times of transmission CH1 */

/* LED lighting pattern */
#define READ_ERR_CH0        LED_1   /* read  cycle error CH0 */
#define READ_ERR_CH1        LED_2   /* read  cycle error CH1 */
#define WRITE_ERR_CH0       LED_3   /* write cycle error CH0 */
#define WRITE_ERR_CH1       LED_4   /* write cycle error CH1 */
#define RR_ERR_BOTH         LED_5   /* read  cycle error CH0 & read  cycle error CH1 */
#define WR_ERR_BOTH         LED_6   /* write cycle error CH0 & read  cycle error CH1 */
#define RW_ERR_BOTH         LED_7   /* read  cycle error CH0 & write cycle error CH1 */
#define WW_ERR_BOTH         LED_8   /* write cycle error CH0 & write cycle error CH1 */

/* functions */
int main(void);                                         /* main routine */
static void reg_irq_handler(void);                      /* registration of IRQ handler */
static void setup_dmac(UWORD,UWORD,UWORD,HWORD*,UWORD);  /* setup Channel */
static void dmacCH0_handler(void);                      /* DMAC CH0 interrupt handler */
static void dmacCH1_handler(void);                      /* DMAC CH1 interrupt handler */

/* global variables */
static volatile unsigned int ch0_flag;  /* end flag CH0(0: dma ch0 not end,
                                                        1: dma ch0 end) */
static volatile unsigned int ch1_flag;  /* end flag CH1(0: dma ch1 not end,
                                                        1: dma ch1 end) */
static volatile unsigned int err_sta;   /* error status(0x00: no error
                                        0x01: read  cycle error CH0,0x02: read  cycle error CH1,
                                        0x04: write cycle error CH0,0x08: write cycle error CH1,
                                        0x03: read  cycle error CH0 & read  cycle error CH1,
                                        0x06: write cycle error CH0 & read  cycle error CH1,
                                        0x09: read  cycle error CH0 & write cycle error CH1,
                                        0x0c: write cycle error CH0 & write cycle error CH1)*/

/****************************************************************************/
/*  Entry point                                                             */
/*  Function : main                                                         */
/*      Parameters                                                          */
/*          Input   :   Nothing                                             */
/*          Output  :   0                                                   */
/****************************************************************************/
int main(void)
{
    /* initialize irq */
    init_irq();

    /* registration of IRQ handler */
    reg_irq_handler();

    /* initialize LED */
    init_led();   /* set output mode */

    led_on(LED_START_PATTERN);  /* light LED start pattern */

    /* initialize variables */
    ch0_flag = 0;
    ch1_flag = 0;
    err_sta  = 0x00;

    /* the order of priority */
    put_wvalue(DMAMOD,DMAMOD_FIX);  /* priority of DMA channel : CH0 > CH1 */

    /* setup DMAC CH0 */
    setup_dmac(DMAC_BASE0,CH0_MODE,CH0_S_START_ADD,CH0_D_START_ADD,NUM_OF_TIME_CH0);

    /* setup DMAC CH1 */
    setup_dmac(DMAC_BASE1,CH1_MODE,CH1_S_START_ADD,CH1_D_START_ADD,NUM_OF_TIME_CH1);

    /* enable IRQ */
#ifdef __IAR__
    __enable_interrupt();
#else
    irq_en();
#endif

    /* DMA transmit start */
    clr_wbit(DMACMSK0,(UWORD)DMACMSK_MSK); /* CH0 start */
    clr_wbit(DMACMSK1,(UWORD)DMACMSK_MSK); /* CH1 start */

    while((ch0_flag == 0)||(ch1_flag == 0 ))  /* DMA transfer end ? */
        ;

    /* end pattern */
    switch(err_sta){
        case (0x00):            /* normal end */
            led_on(LED_NORMAL_END_PATTERN);
            break;
        case (0x01):            /* CH0 read cycle error */
            led_on(READ_ERR_CH0);
            break;
        case (0x02):            /* CH1 read cycle error */
            led_on(READ_ERR_CH1);
            break;
        case (0x04):            /* CH0 write cycle error */
            led_on(WRITE_ERR_CH0);
            break;
        case (0x08):            /* CH1 write cycle error */
            led_on(WRITE_ERR_CH1);
            break;
        case (0x03):            /* CH0 read  cycle error & CH1 read  cycle error */
            led_on(RR_ERR_BOTH);
            break;
        case (0x06):            /* CH0 write cycle error & CH1 read  cycle error */
            led_on(WR_ERR_BOTH);
            break;
        case (0x09):            /* CH0 read  cycle error & CH1 write cycle error */
            led_on(RW_ERR_BOTH);
            break;
        case (0x0c):            /* CH0 write cycle error & CH1 write cycle error */
            led_on(WW_ERR_BOTH);
            break;
        default:
            break;
    }
    put_wvalue(ILC0, 0x0);  /* disable all interrupts */
    put_wvalue(ILC1, 0x0);  /* disable all interrupts */

#ifdef __IAR__
    __disable_interrupt();
#else
    irq_dis();  /* disable all interrupts */
#endif

    return(0);
}
/****************************************************************************/
/*  Setup of DMAC                                                           */
/*  Function : setup_dmac(UWORD,UWORD,UWORD,UWORD,UWORD)                    */
/*      Parameters                                                          */
/*          Input   : UWORD dmac_add    ... dmac channel base address       */
/*                          mode        ... dmac setting mode               */
/*                          s_add       ... source data start address       */
/*                          d_add       ... destination data start address  */
/*                          num_of_time ... number of time of transmit      */
/*          Output  : Nothing                                               */
/****************************************************************************/
void setup_dmac(UWORD dmac_add,UWORD mode,UWORD s_add,HWORD* d_add,UWORD num_of_time)
{
    set_wbit((dmac_add + MSK),DMACMSK_MSK);     /* DMA stop  */

    put_wvalue((dmac_add + CINT),0x00ff);       /* end status clear */

    /* setup mode */
    put_wvalue((dmac_add + TMOD),mode);

    put_wvalue((dmac_add + SAD),s_add); /* set source data start address */

    put_wvalue((dmac_add + DAD),(UWORD)d_add); /* set destination data start address */

    put_wvalue((dmac_add + SIZ),num_of_time);   /* set the number of times
                                                                of transmission */

    return;
}
/*****************************************************************************/
/*  DMAC CH0 interrupt handler                                               */
/*      Function : dmacCH0_handler(void)                                     */
/*          Parameters                                                       */
/*              Input  : Nothing                                             */
/*              Output : Nothing                                             */
/*****************************************************************************/
void dmacCH0_handler(void)
{
    UWORD sta = get_wvalue(DMAINT);

    set_wbit(DMACMSK0,DMACMSK_MSK); /* DMA CH0 stop */

    put_wvalue(DMACCINT0,0x00ff);   /* end status clear */

    if(sta & DMAINT_ISTA0){ /* error end ? */
        if(sta & DMAINT_ISTP0)  /* when did the error occur? */
            err_sta |= 0x04;   /* write cycle error */

        else
            err_sta |= 0x01;    /* read cycle error */
    }
    else
        ;

    ch0_flag = 1;

    return;
}
/*****************************************************************************/
/*  DMAC CH1 interrupt handler                                               */
/*      Function : dmacCH1_handler(void)                                     */
/*          Parameters                                                       */
/*              Input  : Nothing                                             */
/*              Output : Nothing                                             */
/*****************************************************************************/
void dmacCH1_handler(void)
{
    UWORD sta= get_wvalue(DMAINT);

    set_wbit(DMACMSK1,DMACMSK_MSK); /* DMA CH1 stop */
    put_wvalue(DMACCINT1,0x00ff);   /* end status clear */

    if(sta & DMAINT_ISTA1){     /* error end ? */
        if(sta & DMAINT_ISTP1)      /* when did the error occur? */
            err_sta |= 0x08;    /* write cycle error */

        else
            err_sta |= 0x02;    /* read cycle error */
    }
    else
        ;

    ch1_flag = 1;

    return;
}
/****************************************************************************/
/*  Registration of IRQ Handler                                             */
/*  Function : reg_irq_handler                                              */
/*      Parameters                                                          */
/*          Input   :   Nothing                                             */
/*          Output  :   Nothing                                             */
/*  Note : Initialize of IRQ needs to be performed before this process.     */
/****************************************************************************/
void reg_irq_handler(void)
{
    /* register IRQ handlers into handler table */
    IRQ_HANDLER_TABLE[INT_DMA0] = dmacCH0_handler;
    IRQ_HANDLER_TABLE[INT_DMA1] = dmacCH1_handler;

    /* setup interrupt level */
    set_wbit(EXILCA, ILC_ILC24 & ILC_INT_LV7);/* dma handler(nIRQ[24]) -> level7 */

    return;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?