SAML21: Add DMA descriptor management logic

This commit is contained in:
Gregory Nutt 2015-06-14 08:48:25 -06:00
parent 41fa4c7dbe
commit 6b8ae61dad
6 changed files with 307 additions and 43 deletions

View File

@ -84,6 +84,7 @@
# define SAMDL_FLASH_SIZE (16*1024) /* 16KB */
# define SAMDL_SRAM0_SIZE (2*1024) /* 2KB */
# define SAMDL_LPRAM_SIZE (0*1024) /* None */
#elif defined(CONFIG_ARCH_CHIP_SAMD20E15)
@ -96,6 +97,7 @@
# define SAMDL_FLASH_SIZE (32*1024) /* 32KB */
# define SAMDL_SRAM0_SIZE (4*1024) /* 4KB */
# define SAMDL_LPRAM_SIZE (0*1024) /* None */
#elif defined(CONFIG_ARCH_CHIP_SAMD20E16)
@ -108,6 +110,7 @@
# define SAMDL_FLASH_SIZE (64*1024) /* 64KB */
# define SAMDL_SRAM0_SIZE (8*1024) /* 8KB */
# define SAMDL_LPRAM_SIZE (0*1024) /* None */
#elif defined(CONFIG_ARCH_CHIP_SAMD20E17)
@ -120,6 +123,7 @@
# define SAMDL_FLASH_SIZE (128*1024) /* 128KB */
# define SAMDL_SRAM0_SIZE (16*1024) /* 16KB */
# define SAMDL_LPRAM_SIZE (0*1024) /* None */
#elif defined(CONFIG_ARCH_CHIP_SAMD20E18)
@ -132,6 +136,7 @@
# define SAMDL_FLASH_SIZE (256*1024) /* 256KB */
# define SAMDL_SRAM0_SIZE (32*1024) /* 32KB */
# define SAMDL_LPRAM_SIZE (0*1024) /* None */
#elif defined(CONFIG_ARCH_CHIP_SAMD20G14)
@ -144,6 +149,7 @@
# define SAMDL_FLASH_SIZE (16*1024) /* 16KB */
# define SAMDL_SRAM0_SIZE (2*1024) /* 2KB */
# define SAMDL_LPRAM_SIZE (0*1024) /* None */
#elif defined(CONFIG_ARCH_CHIP_SAMD20G15)
@ -156,6 +162,7 @@
# define SAMDL_FLASH_SIZE (32*1024) /* 32KB */
# define SAMDL_SRAM0_SIZE (4*1024) /* 4KB */
# define SAMDL_LPRAM_SIZE (0*1024) /* None */
#elif defined(CONFIG_ARCH_CHIP_SAMD20G16)
@ -168,6 +175,7 @@
# define SAMDL_FLASH_SIZE (64*1024) /* 64KB */
# define SAMDL_SRAM0_SIZE (8*1024) /* 8KB */
# define SAMDL_LPRAM_SIZE (0*1024) /* None */
#elif defined(CONFIG_ARCH_CHIP_SAMD20G17)
@ -180,6 +188,7 @@
# define SAMDL_FLASH_SIZE (128*1024) /* 128KB */
# define SAMDL_SRAM0_SIZE (16*1024) /* 16KB */
# define SAMDL_LPRAM_SIZE (0*1024) /* None */
#elif defined(CONFIG_ARCH_CHIP_SAMD20G18)
@ -192,6 +201,7 @@
# define SAMDL_FLASH_SIZE (256*1024) /* 256KB */
# define SAMDL_SRAM0_SIZE (32*1024) /* 32KB */
# define SAMDL_LPRAM_SIZE (0*1024) /* None */
#elif defined(CONFIG_ARCH_CHIP_SAMD20J14)
@ -204,6 +214,7 @@
# define SAMDL_FLASH_SIZE (16*1024) /* 16KB */
# define SAMDL_SRAM0_SIZE (2*1024) /* 2KB */
# define SAMDL_LPRAM_SIZE (0*1024) /* None */
#elif defined(CONFIG_ARCH_CHIP_SAMD20J15)
@ -216,6 +227,7 @@
# define SAMDL_FLASH_SIZE (32*1024) /* 32KB */
# define SAMDL_SRAM0_SIZE (4*1024) /* 4KB */
# define SAMDL_LPRAM_SIZE (0*1024) /* None */
#elif defined(CONFIG_ARCH_CHIP_SAMD20J16)
@ -228,6 +240,7 @@
# define SAMDL_FLASH_SIZE (64*1024) /* 64KB */
# define SAMDL_SRAM0_SIZE (8*1024) /* 8KB */
# define SAMDL_LPRAM_SIZE (0*1024) /* None */
#elif defined(CONFIG_ARCH_CHIP_SAMD20J17)
@ -240,6 +253,7 @@
# define SAMDL_FLASH_SIZE (128*1024) /* 128KB */
# define SAMDL_SRAM0_SIZE (16*1024) /* 16KB */
# define SAMDL_LPRAM_SIZE (0*1024) /* None */
#elif defined(CONFIG_ARCH_CHIP_SAMD20J18)
@ -252,6 +266,7 @@
# define SAMDL_FLASH_SIZE (256*1024) /* 256KB */
# define SAMDL_SRAM0_SIZE (32*1024) /* 32KB */
# define SAMDL_LPRAM_SIZE (0*1024) /* None */
#else
@ -383,6 +398,7 @@
# define SAMDL_FLASH_SIZE (32*1024) /* 32KB */
# define SAMDL_FLASHRWW_SIZE (1*1024) /* 1KB */
# define SAMDL_SRAM0_SIZE (4*1024) /* 4KB */
# define SAMDL_LPRAM_SIZE (2*1024) /* 2KB */
/* TCC waveform outputs */
@ -400,6 +416,7 @@
# define SAMDL_FLASH_SIZE (64*1024) /* 64KB */
# define SAMDL_FLASHRWW_SIZE (2*1024) /* 2KB */
# define SAMDL_SRAM0_SIZE (8*1024) /* 8KB */
# define SAMDL_LPRAM_SIZE (4*1024) /* 4KB */
/* TCC waveform outputs */
@ -417,6 +434,7 @@
# define SAMDL_FLASH_SIZE (128*1024) /* 128KB */
# define SAMDL_FLASHRWW_SIZE (4*1024) /* 4KB */
# define SAMDL_SRAM0_SIZE (16*1024) /* 16KB */
# define SAMDL_LPRAM_SIZE (8*1024) /* 8KB */
/* TCC waveform outputs */
@ -434,6 +452,7 @@
# define SAMDL_FLASH_SIZE (256*1024) /* 256KB */
# define SAMDL_FLASHRWW_SIZE (8*1024) /* 8KB */
# define SAMDL_SRAM0_SIZE (32*1024) /* 32KB */
# define SAMDL_LPRAM_SIZE (8*1024) /* 8KB */
/* TCC waveform outputs */
@ -451,6 +470,7 @@
# define SAMDL_FLASH_SIZE (64*1024) /* 64KB */
# define SAMDL_FLASHRWW_SIZE (2*1024) /* 2KB */
# define SAMDL_SRAM0_SIZE (8*1024) /* 8KB */
# define SAMDL_LPRAM_SIZE (4*1024) /* 4KB */
/* TCC waveform outputs */
@ -465,9 +485,10 @@
/* Internal memory */
# define SAMDL_FLASH_SIZE (128*1024) /* 128KB */
# define SAMDL_FLASHRWW_SIZE (4*1024) /* 4KB */
# define SAMDL_SRAM0_SIZE (16*1024) /* 16KB */
# define SAMDL_FLASH_SIZE (128*1024) /* 128KB */
# define SAMDL_FLASHRWW_SIZE (4*1024) /* 4KB */
# define SAMDL_SRAM0_SIZE (16*1024) /* 16KB */
# define SAMDL_LPRAM_SIZE (8*1024) /* 8KB */
/* TCC waveform outputs */
@ -482,9 +503,10 @@
/* Internal memory */
# define SAMDL_FLASH_SIZE (256*1024) /* 256KB */
# define SAMDL_FLASHRWW_SIZE (8*1024) /* 8KB */
# define SAMDL_SRAM0_SIZE (32*1024) /* 32KB */
# define SAMDL_FLASH_SIZE (256*1024) /* 256KB */
# define SAMDL_FLASHRWW_SIZE (8*1024) /* 8KB */
# define SAMDL_SRAM0_SIZE (32*1024) /* 32KB */
# define SAMDL_LPRAM_SIZE (8*1024) /* 8KB */
/* TCC waveform outputs */
@ -502,6 +524,7 @@
# define SAMDL_FLASH_SIZE (64*1024) /* 64KB */
# define SAMDL_FLASHRWW_SIZE (2*1024) /* 2KB */
# define SAMDL_SRAM0_SIZE (8*1024) /* 8KB */
# define SAMDL_LPRAM_SIZE (8*1024) /* 4KB */
/* TCC waveform outputs */
@ -519,6 +542,7 @@
# define SAMDL_FLASH_SIZE (128*1024) /* 128KB */
# define SAMDL_FLASHRWW_SIZE (4*1024) /* 4KB */
# define SAMDL_SRAM0_SIZE (16*1024) /* 16KB */
# define SAMDL_LPRAM_SIZE (8*1024) /* 8KB */
/* TCC waveform outputs */
@ -536,6 +560,7 @@
# define SAMDL_FLASH_SIZE (256*1024) /* 256KB */
# define SAMDL_FLASHRWW_SIZE (8*1024) /* 8KB */
# define SAMDL_SRAM0_SIZE (32*1024) /* 32KB */
# define SAMDL_LPRAM_SIZE (8*1024) /* 8KB */
/* TCC waveform outputs */

View File

@ -1384,7 +1384,7 @@ void weak_function up_dmainitialize(void)
/* Initialize semaphores */
sem_init(&g_chsem, 0, 1);
sem_init(&g_dsem, 0, SAM34_NDMACHAN);
sem_init(&g_dsem, 0, CONFIG_SAM34_NLLDESC);
}
/****************************************************************************

View File

@ -241,6 +241,7 @@ config ARCH_FAMILY_SAMD20J
config ARCH_FAMILY_SAML21
bool
default n
selest SAMDL_HAVE_DMAC
config ARCH_FAMILY_SAML21E
bool
@ -261,6 +262,12 @@ config ARCH_FAMILY_SAML21J
select SAMDL_HAVE_TC3
select SAMDL_HAVE_TC5
menu "SAMD/L Peripheral Support"
config SAMDL_HAVE_DMAC
bool
default n
config SAMDL_HAVE_SERCOM4
bool
default n
@ -289,8 +296,6 @@ config SAMDL_HAVE_TC7
bool
default n
menu "SAMD/L Peripheral Support"
config SAMDL_AC
bool "Analog Comparator"
default n
@ -307,7 +312,7 @@ config SAMDL_DMAC
bool "DMA Controller"
default n
select ARCH_DMA
depends on EXPERIMENTAL
depends on SAMDL_HAVE_DMAC && EXPERIMENTAL
config SAMDL_EVSYS
bool "Event System"
@ -414,6 +419,11 @@ config SAMDL_SERCOM0_ISUSART
endchoice
config SAMDL_DMAC_NDESC
int "Number of DMA Descriptors"
default 64
depends on SAMDL_DMAC
choice
prompt "SERCOM1 mode"
default SAMDL_SERCOM1_ISUSART

View File

@ -365,6 +365,16 @@ trigger */
/********************************************************************************************
* Public Types
********************************************************************************************/
/* DMA descriptor */
struct dma_desc_s
{
uint16_t btctrl; /* Block Transfer Control Register */
uint16_t btcnt; /* Block Transfer Count Register */
uint32_t srcaddr; /* Block Transfer Source Address Register */
uint32_t dstaddr; /* Block Transfer Destination Address Register */
uint32_t descaddr; /* Next Address Descriptor Register */
};
/********************************************************************************************
* Public Data

View File

@ -74,6 +74,12 @@
# warning "SAM3/4 DMA enabled but CONFIG_ARCH_DMA disabled"
#endif
/* Number of DMA descriptors in LPRAM */
#ifndef CONFIG_SAMDL_DMAC_NDESC
# define CONFIG_SAMDL_DMAC_NDESC 64
#endif
/****************************************************************************
* Private Types
****************************************************************************/
@ -82,25 +88,56 @@
struct sam_dmach_s
{
uint8_t dc_chan; /* DMA channel number (0-6) */
bool dc_inuse; /* TRUE: The DMA channel is in use */
uint32_t dc_flags; /* DMA channel flags */
dma_callback_t dc_callback; /* Callback invoked when the DMA completes */
void *dc_arg; /* Argument passed to callback function */
uint8_t dc_chan; /* DMA channel number (0-6) */
bool dc_inuse; /* TRUE: The DMA channel is in use */
uint32_t dc_flags; /* DMA channel flags */
dma_callback_t dc_callback; /* Callback invoked when the DMA completes */
void *dc_arg; /* Argument passed to callback function */
struct dma_desc_s *llhead; /* DMA link list head */
struct dma_desc_s *lltail; /* DMA link list head */
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static void sam_takechsem(void);
static inline void sam_givechsem(void);
static void sam_takedsem(void);
static inline void sam_givedsem(void);
static void sam_dmaterminate(struct sam_dmach_s *dmach, int result);
static int sam_dmainterrupt(int irq, void *context);
static struct dma_desc_s *
sam_allocdesc(struct sam_dmach_s *dmach,
struct dma_desc_s *prev, uint16_t btctrl, uint16_t btcnt,
uint32_t srcaddr,uint32_t dstaddr);
static void sam_freelinklist(struct sam_dmach_s *dmach);
static size_t sam_maxtransfer(struct sam_dmach_s *dmach);
static int sam_txbuffer(struct sam_dmach_s *dmach, uint32_t paddr,
uint32_t maddr, size_t nbytes);
static int sam_rxbuffer(struct sam_dmach_s *dmach, uint32_t paddr,
uint32_t maddr, size_t nbytes);
static int sam_single(struct sam_dmach_s *dmach);
static int sam_multiple(struct sam_dmach_s *dmach);
/****************************************************************************
* Private Data
****************************************************************************/
/* These semaphores protect the DMA channel tables */
/* These semaphores protect the DMA channel and descriptor tables */
static sem_t g_chsem;
static sem_t g_dsem;
/* This array describes the state of each DMA channel */
static struct sam_dmach_s g_dmach[SAMDL_NDMACHAN];
/* DMA descriptors positioned in LPRAM */
static struct dma_desc_s g_dma_desc[CONFIG_SAMDL_DMAC_NDESC]
__attribute__ ((section(".lpram"),aligned(16)));
/****************************************************************************
* Private Functions
****************************************************************************/
@ -132,6 +169,33 @@ static inline void sam_givechsem(void)
(void)sem_post(&g_chsem);
}
/****************************************************************************
* Name: sam_takedsem() and sam_givedsem()
*
* Description:
* Used to wait for availability of descriptors in the descriptor table.
*
****************************************************************************/
static void sam_takedsem(void)
{
/* Take the semaphore (perhaps waiting) */
while (sem_wait(&g_dsem) != 0)
{
/* The only case that an error should occur here is if the wait was
* awakened by a signal.
*/
ASSERT(errno == EINTR);
}
}
static inline void sam_givedsem(void)
{
(void)sem_post(&g_dsem);
}
/****************************************************************************
* Name: sam_dmaterminate
*
@ -148,8 +212,9 @@ static void sam_dmaterminate(struct sam_dmach_s *dmach, int result)
/* Disable the channel */
#warning Missing logic
/* Free the resources */
#warning Missing logic
/* Free the linklist */
sam_freelinklist(dmach);
/* Perform the DMA complete callback */
@ -246,6 +311,141 @@ static size_t sam_addrincr(struct sam_dmach_s *dmach)
}
#endif
/****************************************************************************
* Name: sam_allocdesc
*
* Description:
* Allocate and add one descriptor to the DMA channel's link list.
*
* NOTE: link list entries are freed by the DMA interrupt handler. However,
* since the setting/clearing of the 'in use' indication is atomic, no
* special actions need be performed. It would be a good thing to add logic
* to handle the case where all of the entries are exhausted and we could
* wait for some to be freed by the interrupt handler.
*
****************************************************************************/
static struct dma_desc_s *
sam_allocdesc(struct sam_dmach_s *dmach, struct dma_desc_s *prev,
uint16_t btctrl, uint16_t btcnt, uint32_t srcaddr,
uint32_t dstaddr)
{
struct dma_desc_s *desc = NULL;
int i;
/* Sanity check -- src == 0 is the indication that the link is unused.
* Obviously setting it to zero would break that usage.
*/
#ifdef CONFIG_DEBUG
if (src != 0)
#endif
{
/* Table a descriptor table semaphore count. When we get one, then there
* is at least one free descriptor in the table and it is ours.
*/
sam_takedsem();
/* Examine each link list entry to find an available one -- i.e., one
* with src == 0. That src field is set to zero by the DMA transfer
* complete interrupt handler. The following should be safe because
* that is an atomic operation.
*/
sam_takechsem();
for (i = 0; i < CONFIG_SAMDL_DMAC_NDESC; i++)
{
if (g_dma_desc[i].srcaddr == 0)
{
/* We have it. Initialize the new link list entry */
desc = &g_dma_desc[i];
desc->btctrl = btctrl; /* Block Transfer Control Register */
desc->btcnt = btcnt; /* Block Transfer Count Register */
desc->srcaddr = srcaddr; /* Block Transfer Source Address Register */
desc->dstaddr = dstaddr; /* Block Transfer Destination Address Register */
desc->descaddr = 0; /* Next Address Descriptor Register */
/* And then hook it at the tail of the link list */
if (!prev)
{
/* There is no previous link. This is the new head of
* the list
*/
DEBUGASSERT(dmach->llhead == NULL && dmach->lltail == NULL);
dmach->llhead = desc;
}
else
{
DEBUGASSERT(dmach->llhead != NULL && dmach->lltail == prev);
/* When the second link is added to the list, that is the
* cue that we are going to do the link list transfer.
*/
#warning Missing logic
/* Link the previous tail to the new tail */
prev->descaddr = (uint32_t)desc;
}
/* In any event, this is the new tail of the list. */
#warning Missing logic
dmach->lltail = desc;
break;
}
}
/* Because we hold a count from the counting semaphore, the above
* search loop should always be successful.
*/
sam_givechsem();
DEBUGASSERT(desc != NULL);
}
return desc;
}
/****************************************************************************
* Name: sam_freelinklist
*
* Description:
* Free all descriptors in the DMA channel's link list.
*
* NOTE: Called from the DMA interrupt handler.
*
****************************************************************************/
static void sam_freelinklist(struct sam_dmach_s *dmach)
{
struct dma_desc_s *desc;
struct dma_desc_s *next;
/* Get the head of the link list and detach the link list from the DMA
* channel
*/
desc = dmach->llhead;
dmach->llhead = NULL;
dmach->lltail = NULL;
/* Reset each descriptor in the link list (thereby freeing them) */
while (desc != NULL)
{
next = (struct dma_desc_s *)desc->descaddr;
DEBUGASSERT(desc->src != 0);
memset(desc, 0, sizeof(struct dma_desc_s));
sam_givedsem();
desc = next;
}
}
/****************************************************************************
* Name: sam_maxtransfer
*
@ -273,7 +473,18 @@ static size_t sam_maxtransfer(struct sam_dmach_s *dmach)
static int sam_txbuffer(struct sam_dmach_s *dmach, uint32_t paddr,
uint32_t maddr, size_t nbytes)
{
uint16_t btctrl;
uint16_t btcnt;
#warning Missing logic
/* Add the new link list entry */
if (!sam_allocdesc(dmach, dmach->lltail, btctrl, btcnt, maddr, paddr))
{
return -ENOMEM;
}
return OK;
}
@ -290,7 +501,18 @@ static int sam_txbuffer(struct sam_dmach_s *dmach, uint32_t paddr,
static int sam_rxbuffer(struct sam_dmach_s *dmach, uint32_t paddr,
uint32_t maddr, size_t nbytes)
{
uint16_t btctrl;
uint16_t btcnt;
#warning Missing logic
/* Add the new link list entry */
if (!sam_allocdesc(dmach, dmach->lltail, btctrl, btcnt, maddr, paddr))
{
return -ENOMEM;
}
return OK;
}
@ -302,8 +524,10 @@ static int sam_rxbuffer(struct sam_dmach_s *dmach, uint32_t paddr,
*
****************************************************************************/
static inline int sam_single(struct sam_dmach_s *dmach)
static int sam_single(struct sam_dmach_s *dmach)
{
struct dma_desc_s *llhead = dmach->llhead;
/* Clear any pending interrupts from any previous DMAC transfer.
*
* REVISIT: If DMAC interrupts are disabled at the NVIKC, then reading the
@ -313,6 +537,7 @@ static inline int sam_single(struct sam_dmach_s *dmach)
/* Set up the DMA */
#warning Missing logic
DEBUGASSERT(llhead != NULL && llhead->src != 0);
/* Enable the channel */
#warning Missing logic
@ -331,8 +556,10 @@ static inline int sam_single(struct sam_dmach_s *dmach)
*
****************************************************************************/
static inline int sam_multiple(struct sam_dmach_s *dmach)
static int sam_multiple(struct sam_dmach_s *dmach)
{
struct dma_desc_s *llhead = dmach->llhead;
/* Clear any pending interrupts from any previous DMAC transfer.
*
* REVISIT: If DMAC interrupts are disabled at the NVIKC, then reading the
@ -342,6 +569,8 @@ static inline int sam_multiple(struct sam_dmach_s *dmach)
/* Set up the initial DMA */
#warning Missing logic
DEBUGASSERT(llhead != NULL && llhead->src != 0);
/* Enable the channel */
#warning Missing logic
@ -375,6 +604,7 @@ void weak_function up_dmainitialize(void)
/* Initialize global semaphores */
sem_init(&g_chsem, 0, 1);
sem_init(&g_dsem, 0, CONFIG_SAMDL_DMAC_NDESC);
/* Initialized the DMA channel table */
@ -676,9 +906,11 @@ int sam_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg)
dmavdbg("dmach: %p callback: %p arg: %p\n", dmach, callback, arg);
DEBUGASSERT(dmach != NULL);
/* Verify that the DMA has been setup */
#warning Missing logic
/* Verify that the DMA has been setup (i.e., at least one entry in the
* link list).
*/
if (dmach->llhead)
{
/* Save the callback info. This will be invoked when the DMA completes */
@ -686,9 +918,8 @@ int sam_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg)
dmach->dc_arg = arg;
/* Is this a single block transfer? Or a multiple block transfer? */
#warning Missing logic
if (true)
if (dmach->llhead == dmach->lltail)
{
ret = sam_single(dmach);
}
@ -766,16 +997,6 @@ void sam_dmasample(DMA_HANDLE handle, struct sam_dmaregs_s *regs)
regs->chctrlb = getreg32(SAM_DMAC_CHCTRLB); /* Channel Control B Register */
regs->chintflag = getreg8(SAM_DMAC_CHINTFLAG); /* Channel Interrupt Flag Status and Clear Register */
regs->chstatus = getreg8(SAM_DMAC_CHSTATUS); /* Channel Status Register */
/* LPSRAM Registers Relative to BASEADDR or WRBADDR */
#warning How do we get the base address
regs->btctrl = getreg16(base + SAM_LPSRAM_BTCTRL_OFFSET);
regs->btcnt = getreg16(base + SAM_LPSRAM_BTCNT_OFFSET);
regs->srcaddr = getreg32(base + SAM_LPSRAM_SRCADDR_OFFSET);
regs->dstaddr = getreg32(base + SAM_LPSRAM_DSTADDR_OFFSET);
regs->descaddr = getreg32(base + SAM_LPSRAM_DESCADDR_OFFSET);
irqrestore(flags);
}
#endif /* CONFIG_DEBUG_DMA */
@ -812,14 +1033,6 @@ void sam_dmadump(DMA_HANDLE handle, const struct sam_dmaregs_s *regs,
regs->chid, regs->chctrla, regs->chctrlb, regs->chintflag,
dmadbg(" CHSTATUS: %02x\n",
regs->chstatus);
/* LPSRAM Registers Relative to BASEADDR or WRBADDR */
#warning How do we get the base address
dmadbg(" LPSRAM Values:\n");
dmadbg(" BTCTRL: %04x BTCNT: %04x SRCADDR: %08x DSTADDR: %08x\n",
regs->btctrl, regs->btcnt, regs->srcaddr, regs->dstaddr);
dmadbg(" DESCADDR: %08x\n", regs->descaddr);
}
#endif /* CONFIG_DEBUG_DMA */
#endif /* CONFIG_SAMDL_DMAC */

View File

@ -34,13 +34,15 @@
****************************************************************************/
/* The ATSAML21J18A has 256KB of FLASH beginning at address 0x0000:0000 and
* 32KB of SRAM beginning at address 0x2000:0000
* 32KB of SRAM beginning at address 0x2000:0000. There is also 8KB low-
* power SRAM at 0x30000000 that may be used by the DMAC.
*/
MEMORY
{
flash (rx) : ORIGIN = 0x00000000, LENGTH = 256K
sram (rwx) : ORIGIN = 0x20000000, LENGTH = 32K
lpram (rw) : ORIGIN = 0x30000000, LENGTH = 8K
}
OUTPUT_ARCH(arm)
@ -107,6 +109,10 @@ SECTIONS
_ebss = ABSOLUTE(.);
} > sram
.lpram : {
*(.lpram)
} > lpram
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }