From cb96ac9be7c298f0e0634a048d938b68a3f57ed0 Mon Sep 17 00:00:00 2001 From: asterix Date: Tue, 6 Sep 2011 15:15:06 +0000 Subject: [PATCH] Add dmac driver for sam3x. git-svn-id: https://src.develer.com/svnoss/bertos/trunk@5035 38d2e660-2303-0410-9eaa-f027e97ec537 --- bertos/cpu/cortex-m3/drv/dmac_sam3.c | 180 +++++++++++++++++++++++++++ bertos/cpu/cortex-m3/drv/dmac_sam3.h | 73 +++++++++++ 2 files changed, 253 insertions(+) create mode 100644 bertos/cpu/cortex-m3/drv/dmac_sam3.c create mode 100644 bertos/cpu/cortex-m3/drv/dmac_sam3.h diff --git a/bertos/cpu/cortex-m3/drv/dmac_sam3.c b/bertos/cpu/cortex-m3/drv/dmac_sam3.c new file mode 100644 index 00000000..21045b7f --- /dev/null +++ b/bertos/cpu/cortex-m3/drv/dmac_sam3.c @@ -0,0 +1,180 @@ +/** + * \file + * + * + * \brief HSMCI driver implementation. + * + * \author Daniele Basile + */ + +#include "dmac_sam3.h" + +#include "hsmci_sam3.h" +#include "hw/hw_sd.h" + +#include +#include + +#include +#include + +#include + +struct DmacCh +{ + reg32_t *src; + reg32_t *dst; + reg32_t *desc; + reg32_t *cfg; + reg32_t *ctrla; + reg32_t *ctrlb; +}; + +#define DMAC_CHANNEL_CNT 5 +struct DmacCh dmac_ch[] = +{ + { + .src = &DMAC_SADDR0, + .dst = &DMAC_DADDR0, + .desc = &DMAC_DSCR0, + .cfg = &DMAC_CFG0, + .ctrla = &DMAC_CTRLA0, + .ctrlb = &DMAC_CTRLB0, + }, + { + .src = &DMAC_SADDR1, + .dst = &DMAC_DADDR1, + .desc = &DMAC_DSCR1, + .cfg = &DMAC_CFG1, + .ctrla = &DMAC_CTRLA1, + .ctrlb = &DMAC_CTRLB1, + }, + { + .src = &DMAC_SADDR2, + .dst = &DMAC_DADDR2, + .desc = &DMAC_DSCR2, + .cfg = &DMAC_CFG2, + .ctrla = &DMAC_CTRLA2, + .ctrlb = &DMAC_CTRLB2, + }, + { + .src = &DMAC_SADDR3, + .dst = &DMAC_DADDR3, + .desc = &DMAC_DSCR3, + .cfg = &DMAC_CFG3, + .ctrla = &DMAC_CTRLA3, + .ctrlb = &DMAC_CTRLB3, + }, + { + .src = &DMAC_SADDR4, + .dst = &DMAC_DADDR4, + .desc = &DMAC_DSCR4, + .cfg = &DMAC_CFG4, + .ctrla = &DMAC_CTRLA4, + .ctrlb = &DMAC_CTRLB4, + }, + { + .src = &DMAC_SADDR5, + .dst = &DMAC_DADDR5, + .desc = &DMAC_DSCR5, + .cfg = &DMAC_CFG5, + .ctrla = &DMAC_CTRLA5, + .ctrlb = &DMAC_CTRLB5, + }, +}; + +void dmac_setSources(Dmac *dmac, uint8_t ch, uint32_t src, uint32_t dst, size_t transfer_size) +{ + ASSERT(ch <= DMAC_CHANNEL_CNT); + + DMAC_CHDR = BV(ch); + + *dmac_ch[ch].src = src; + *dmac_ch[ch].dst = dst; + *dmac_ch[ch].desc = 0; + dmac->transfer_size = transfer_size; +} + +void dmac_configureDmac(Dmac *dmac, uint8_t ch, uint32_t cfg, uint32_t ctrla, uint32_t ctrlb) +{ + ASSERT(ch <= DMAC_CHANNEL_CNT); + + DMAC_CHDR = BV(ch); + + *dmac_ch[ch].cfg = cfg | DMAC_CFG_FIFOCFG_ALAP_CFG | (0x1 << DMAC_CFG_AHB_PROT_SHIFT); + *dmac_ch[ch].ctrla = ctrla | (dmac->transfer_size & DMAC_CTRLA_BTSIZE_MASK); + *dmac_ch[ch].ctrlb = ctrlb | BV(DMAC_CTRLB_IEN); +} + +int dmac_start(Dmac *dmac, uint8_t ch) +{ + ASSERT(ch <= DMAC_CHANNEL_CNT); + + if (DMAC_CHSR & BV(ch)) + { + dmac->errors |= DMAC_ERR_CH_ALREDY_ON; + return -1; + } + + DMAC_CHER = BV(ch); + return 0; +} + +bool dmac_isDone(Dmac *dmac, uint8_t ch) +{ + (void)dmac; + return (DMAC_EBCISR |= BV(ch)); +} + +bool dmac_waitDone(Dmac *dmac, uint8_t ch) +{ + (void)dmac; + while(!(DMAC_EBCISR |= BV(ch))) + cpu_relax(); + + return true; +} + +static DECLARE_ISR(dmac_irq) +{ +} + +void dmac_init(Dmac *dmac) +{ + (void)dmac; + + //init DMAC + DMAC_EBCIDR = 0x3FFFFF; + DMAC_CHDR = 0x1F; + + pmc_periphEnable(DMAC_ID); + DMAC_EN = BV(DMAC_EN_ENABLE); + sysirq_setHandler(INT_DMAC, dmac_irq); +} diff --git a/bertos/cpu/cortex-m3/drv/dmac_sam3.h b/bertos/cpu/cortex-m3/drv/dmac_sam3.h new file mode 100644 index 00000000..41aeb80b --- /dev/null +++ b/bertos/cpu/cortex-m3/drv/dmac_sam3.h @@ -0,0 +1,73 @@ +/** + * \file + * + * + * \brief DMAC utility interface. + * + * \author Daniele Basile + */ + +#ifndef DRV_DMAC_SAM3_H +#define DRV_DMAC_SAM3_H + +#include + +#include + +/** + * DMA Transfer Descriptor as well as Linked List Item + */ +typedef struct DmacDesc +{ + uint32_t src_addr; ///< Source buffer address + uint32_t dst_addr; ///< Destination buffer address + uint32_t ctrl_a; ///< Control A register settings + uint32_t ctrl_b; ///< Control B register settings + uint32_t dsc_addr; ///< Next descriptor address +} DmacDesc; + +typedef struct Dmac +{ + uint8_t errors; + size_t transfer_size; +} Dmac; + +#define DMAC_ERR_CH_ALREDY_ON BV(0) + +void dmac_setSources(Dmac *dmac, uint8_t ch, uint32_t src, uint32_t dst, size_t transfer_size); +void dmac_configureDmac(Dmac *dmac, uint8_t ch, uint32_t cfg, uint32_t ctrla, uint32_t ctrlb); +int dmac_start(Dmac *dmac, uint8_t ch); +bool dmac_isDone(Dmac *dmac, uint8_t ch); +bool dmac_waitDone(Dmac *dmac, uint8_t ch); + +void dmac_init(Dmac *dmac); + +#endif /* DRV_DMAC_SAM3_H */ -- 2.25.1