MKMxxZxxACxx5 Bare Metal Software Drivers  R4.1.6
Reference Manual
DMA Applying Access Protection

This example shows use of the Direct Memory Access (DMA) protection mechanism. The MPU configures dstbuff[] memory array for privileged RW access from DMA master (user secure/non-secure RW accesses are not allowed). Consequently, provided the DMA channel, used to copy srcbuff[] to dstbuff[], is configured for privileged RW access then any writes to the dstbuff[] are allowed and buffers are copied successfully. On the contrary, if the DMA channel, copying srcbuff[] to dstbuff[], is configured for user RW access then any writes to the dstbuff[] are blocked and generates Hard Fault.

Source code:
/******************************************************************************
* (c) Copyright 2010-2015, Freescale Semiconductor Inc.
* ALL RIGHTS RESERVED.
******************************************************************************
* dmaaccess_test.c
******************************************************************************/
#include "drivers.h"
/* Imported symbols from linker */
#if defined (__ICCARM__) || defined(__GNUC__)
extern char __ICFEDIT_region_ROM_start__[];
extern char __ICFEDIT_region_ROM_end__[];
extern char __ICFEDIT_region_RAM_start__[];
extern char __ICFEDIT_region_RAM_end__[];
extern char __ICFEDIT_region_PRIVRAM_start__[];
extern char __ICFEDIT_region_PRIVRAM_end__[];
#define ROM_START_ADDR __ICFEDIT_region_ROM_start__
#define ROM_END_ADDR __ICFEDIT_region_ROM_end__
#define RAM_START_ADDR __ICFEDIT_region_RAM_start__
#define RAM_END_ADDR __ICFEDIT_region_RAM_end__
#define PRIVRAM_START_ADDR __ICFEDIT_region_PRIVRAM_start__
#define PRIVRAM_END_ADDR __ICFEDIT_region_PRIVRAM_end__
#elif defined(__CC_ARM)
#define ROM_START_ADDR 0x00000000
#define ROM_END_ADDR 0x0001ffff
#define RAM_START_ADDR 0x1ffff000
#define RAM_END_ADDR 0x20001fff
#define PRIVRAM_START_ADDR 0x20002000
#define PRIVRAM_END_ADDR 0x20002fff
#endif
#if defined (__ICCARM__)
#pragma location = "PRIVDATA"
static volatile uint8 dstbuff[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
#elif defined(__GNUC__) || defined(__CC_ARM)
static volatile uint8_t __attribute__((section (".PRIVDATA"))) dstbuff[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
#endif
static volatile uint8 srcbuff[20] = {0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9};
void main (void)
{
register uint16 i=0;
/* Set bus masters attribute to be controlled internally by the core */
TRUE);
/* Initialize RGD1 = Flash; RWX supervisor mode, RWX user mode */
MPU_SPVR_USER,/* DMA */
ROM_START_ADDR,
ROM_END_ADDR));
/* Initialize RGD2 = RAM; RW supervisor mode, RW user mode */
MPU_SPVR_RW, /* DMA */
RAM_START_ADDR,
RAM_END_ADDR));
/* Initialize RGD3 = protected RAM */
/* CM0+ master: RW supervisor mode, RW user mode */
/* DMA master: RW supervisor mode, None user mode */
MPU_SPVR_RW, /* DMA */
PRIVRAM_START_ADDR,
PRIVRAM_END_ADDR));
/* Invalidate overlapping RGD0 */
/* Initialize DMA from privileged mode => channel access will be set to */
/* privileged mode; the transfer will complete successfully */
DMA_AdvInit (DMA0,
DMA_CH_SWTRG_M2M_CN_CONFIG(srcbuff,dstbuff,sizeof(srcbuff)),
while (!DMA_IsDone(DMA0)); /* Wait until transfer is completed */
DMA_Ack(DMA0); /* Acknowledge completed transfer */
/* Switch to user mode */
/* Note that software can clear destination buffer because user access is */
/* allowed for CM0 master */
for (i=0; i<20; i++) { dstbuff[i]=0; }
/* Initialize DMA from user mode => channel access will be set to user mode */
/* Note that this transfer will not be completed because "DMA" master user */
/* secure and unsecure mode accesses to PRIVRAM region are prohibited; the */
/* transfer will terminate with a bus error during its write portion */
DMA_AdvInit (DMA0,
DMA_CH_SWTRG_M2M_CN_CONFIG(srcbuff,dstbuff,sizeof(srcbuff)),
/* Wait until transfer is completed or error condition is set */
while (!DMA_IsDone(DMA0));
/* Software should hang in next loop due to bus error on destination (BED) */
/* flag being asserted during DMA transfer */
while (DMA_IsWrError(DMA0));
}
Linker configuration file:
/*###ICF### Section handled by ICF editor, don't touch! ****/
/*-Editor annotation file-*/
/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */
/*-Specials-*/
define symbol __ICFEDIT_intvec_start__ = 0x00000000;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__ = 0x00000000;
define symbol __ICFEDIT_region_ROM_end__ = 0x0001ffff;
define symbol __ICFEDIT_region_RAM_start__ = 0x1ffff000;
define symbol __ICFEDIT_region_RAM_end__ = 0x20001fff;
define symbol __ICFEDIT_region_PRIVRAM_start__ = 0x20002000;
define symbol __ICFEDIT_region_PRIVRAM_end__ = 0x20002fff;
/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__ = 0x200;
define symbol __ICFEDIT_size_heap__ = 0x200;
/**** End of ICF editor section. ###ICF###*/
define symbol __memcfg_start__ = 0x00000400;
define symbol __mtbram_start__ = 0x1ffff000;
/* Export of symbol */
export symbol __ICFEDIT_region_ROM_start__;
export symbol __ICFEDIT_region_ROM_end__;
export symbol __ICFEDIT_region_RAM_start__;
export symbol __ICFEDIT_region_RAM_end__;
export symbol __ICFEDIT_region_PRIVRAM_start__;
export symbol __ICFEDIT_region_PRIVRAM_end__;
define memory mem with size = 4G;
define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__];
define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__];
define region PRIVRAM_region = mem:[from __ICFEDIT_region_PRIVRAM_start__ to __ICFEDIT_region_PRIVRAM_end__];
define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };
define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { };
initialize manually { readwrite };
initialize manually { section .data};
initialize manually { section .textrw };
initialize manually { section PRIVDATA };
do not initialize { zeroinit };
define block CodeRelocate { section .textrw_init };
define block CodeRelocateRam { section .textrw };
place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
place at address mem:__memcfg_start__ { readonly section .memcfg };
place at address mem:__mtbram_start__ { readwrite section .mtbram };
place in ROM_region { readonly , block CodeRelocate };
place in RAM_region { readwrite, block CodeRelocateRam, block HEAP, block CSTACK };
place in PRIVRAM_region { readwrite section PRIVDATA };
Toolchain support:
IAR EWARM 7.40.7CodeWarrior 10.6KEIL uVision 5.15CrossWorks 3.6ATOLLIC TrueStudio 5.3.0Kinetis Design Studio 3.0.0