SAMV71 Xplained Ultra Software Package 1.3

main.c

Go to the documentation of this file.
00001 /* ----------------------------------------------------------------------------
00002  *         SAM Software Package License 
00003  * ----------------------------------------------------------------------------
00004  * Copyright (c) 2014, Atmel Corporation
00005  *
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are met:
00010  *
00011  * - Redistributions of source code must retain the above copyright notice,
00012  * this list of conditions and the disclaimer below.
00013  *
00014  * Atmel's name may not be used to endorse or promote products derived from
00015  * this software without specific prior written permission.
00016  *
00017  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00019  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
00020  * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00022  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
00023  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00024  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00025  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
00026  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  * ----------------------------------------------------------------------------
00028  */
00029 
00030 
00031 /**
00032  *  \page mpu MPU with SAMV7 Microcontrollers
00033  *
00034  *  \section Purpose
00035  *
00036  *  The MPU example will help new users get familiar with the MPU of cortex-m7
00037  *  on Atmel's SAMV7 family of microcontrollers. This basic application shows 
00038  *  the setup of the basic MPU memory regions and how to use the MPU module.
00039  *
00040  *  \section Requirements
00041  *
00042  *  This package can be used with SAMV7 serial evaluation kits.
00043  *
00044  *  \section Description
00045  *
00046  *  At startup, the program will setup basic memory regions, then user can 
00047  *  update and observe the memory management fault exception through the serial 
00048  *  port.
00049  *
00050  *  \section Usage
00051  *
00052  *  -# Build the program and download it inside the SAM V71 Xplained Ultra board.
00053  *  Please refer to the Getting Started with SAM V71 Microcontrollers.pdf
00054  *  -# On the computer, open and configure a terminal application
00055  *     (e.g. HyperTerminal on Microsoft Windows) with these settings:
00056  *    - 115200 baud rate
00057  *    - 8 bits of data
00058  *    - No parity
00059  *    - 1 stop bit
00060  *    - No flow control
00061  *  -# Start the application.
00062  *  -# In the terminal window, the following text should appear (values depend 
00063  *  on the board and chip used):
00064  *     \code
00065  *      -- MPU Example xxx --
00066  *      -- xxxxxx-xx
00067  *      -- Compiled: xxx xx xxxx xx:xx:xx --
00068  *     \endcode
00069  *
00070  * \section References
00071  * - mpu\main.c
00072  *
00073  */
00074 
00075 /** \file
00076  *
00077  *  This file contains all the specific code for the MPU example.
00078  *
00079  */
00080 
00081 /*----------------------------------------------------------------------------
00082  *        Headers
00083  *----------------------------------------------------------------------------*/
00084 #include "board.h"
00085 #include <stdbool.h>
00086 #include <stdio.h>
00087 
00088 /*----------------------------------------------------------------------------
00089  *        Local definitions
00090  *----------------------------------------------------------------------------*/
00091 
00092 #define MPU_UNPRIVILEGED_RAM_REGION       ( 0 )
00093 #define MPU_PRIVILEGE_RAM_REGION          ( 1 )
00094 #define MPU_PRIVILEGE_RAM_REGION_2        ( 2 )
00095 #define MPU_UNPRIVILEGED_FLASH_REGION     ( 3 )
00096 #define MPU_PRIVILEGED_FLASH_REGION       ( 4 )
00097 #define MPU_PERIPHERALS_REGION_0          ( 5 )
00098 #define MPU_PERIPHERALS_REGION_1          ( 6 )
00099 #define MPU_PIOA_REGION_REGION            ( 7 )
00100 
00101 /**************  Peripherals memory region macros for MPU example ********/
00102 #define MPU_PERIPHERALS_START_ADDRESS_0     0x40000000UL
00103 #define MPU_PERIPHERALS_END_ADDRESS_0       (0x400E0E00UL - 1)
00104 
00105 /**************  Peripherals memory region macros for MPU example ********/
00106 #define MPU_PERIPHERALS_START_ADDRESS_1     0x400E0E00UL
00107 #define MPU_PERIPHERALS_END_ADDRESS_1       0x400E2000UL
00108 
00109 /**************  Peripherals memory sub region macros for MPU example ********/
00110 #define MPU_PIOA_PERIPHERALS_REGION_START_ADDRESS    0x400E0E00UL
00111 #define MPU_PIOA_PERIPHERALS_REGION_END_ADDRESS      0x400E1000UL
00112 
00113 /**************  sram memory  unprivileged for MPU example ********/
00114 #define MPU_SRAM_UNPRIVILEGE_START_ADDRESS      (SRAM_START_ADDRESS+0)
00115 #define MPU_SRAM_UNPRIVILEGE_END_ADDRESS        (SRAM_START_ADDRESS+0x2FFFF)
00116 
00117 /**************  sram memory  privileged for MPU example ********/
00118 #define MPU_SRAM_PRIVILEGE_START_ADDRESS        (SRAM_START_ADDRESS+0x30000)
00119 #define MPU_SRAM_PRIVILEGE_END_ADDRESS          (SRAM_START_ADDRESS+0x4FFFF)
00120 
00121 /**************  Second part of sram memory  privileged for MPU example *******/
00122 #define MPU_SRAM_PRIVILEGE2_START_ADDRESS        (SRAM_START_ADDRESS+0x50000)
00123 #define MPU_SRAM_PRIVILEGE2_END_ADDRESS          (SRAM_START_ADDRESS+0x5FFFF)
00124 
00125 /*----------------------------------------------------------------------------
00126  *        Local Variables
00127  *----------------------------------------------------------------------------*/
00128 /** Flag to indicate whether the SVC is done */
00129 uint32_t dwRaisePriDone = 0;
00130 
00131 /*----------------------------------------------------------------------------
00132  *        Local functions
00133  *----------------------------------------------------------------------------*/
00134 
00135 /**
00136  * \brief Function to raise the privilege, used by the assemble code
00137  */
00138 static void _RaisePrivilege(void)
00139 {
00140     /* As this function is called in privilege mode, we don't need to set the 
00141             privilege mode*/
00142     printf("\n\r-I- Raise to Privilege mode\n\r");
00143     __set_CONTROL(PRIVILEGE_MODE);
00144 }
00145 
00146 /**
00147  * \brief Default SVC interrupt handler.
00148  */
00149 void SVC_Handler(void)
00150 {
00151     /* Set to privilege mode */
00152     __set_CONTROL(PRIVILEGE_MODE);
00153 
00154     /* Set flag */
00155     dwRaisePriDone = 1;
00156 }
00157 
00158 /**
00159  * \brief Default MemManage interrupt handler.
00160  * There is a weak handler by default and if the MPU feature is enabled,
00161  * it must be implemented with the actual handler
00162  */
00163 void MemManage_Handler( void )
00164 {
00165     uint32_t nCfsr, nMmfar;
00166     printf("\n\r-I- Memory Exceptions!!! \n\r");
00167     /* adjust the code to exit the MMF */
00168     nCfsr = SCB->CFSR;
00169     nMmfar = SCB->MMFAR;
00170     if (!(nCfsr & ( 1<< 1))) {
00171         _RaisePrivilege();
00172     }
00173     if ((nMmfar & 0x20400000) || (nMmfar & 0x400E0E00) ) {
00174         _RaisePrivilege();
00175     }
00176     printf("\n\r-I- Exit Memory Exceptions!\n\r");
00177 }
00178 
00179 /**
00180  * \brief Setup a memory region.
00181  */
00182 static void _SetupMPU( void )
00183 {
00184 
00185     uint32_t dwRegionBaseAddr;
00186     uint32_t dwRegionAttr;
00187 
00188     /* Internal flash privilege memory region */
00189     dwRegionBaseAddr = IFLASH_PRIVILEGE_START_ADDRESS |
00190         MPU_REGION_VALID |
00191         MPU_PRIVILEGED_FLASH_REGION;
00192 
00193     dwRegionAttr = MPU_AP_FULL_ACCESS |
00194         MPU_CalMPURegionSize(IFLASH_PRIVILEGE_END_ADDRESS - 
00195                 IFLASH_PRIVILEGE_START_ADDRESS) |
00196         MPU_REGION_ENABLE;
00197 
00198     MPU_SetRegion( dwRegionBaseAddr, dwRegionAttr);
00199 
00200 
00201     /* Internal flash unprivileged memory region */
00202     dwRegionBaseAddr = IFLASH_START_ADDRESS |
00203         MPU_REGION_VALID |
00204         MPU_UNPRIVILEGED_FLASH_REGION;
00205 
00206     dwRegionAttr = MPU_AP_READONLY |
00207         MPU_CalMPURegionSize(IFLASH_END_ADDRESS - IFLASH_START_ADDRESS) |
00208         MPU_REGION_ENABLE;
00209 
00210     MPU_SetRegion( dwRegionBaseAddr, dwRegionAttr);
00211 
00212     /* SRAM memory unprivileged region */
00213     dwRegionBaseAddr = MPU_SRAM_UNPRIVILEGE_START_ADDRESS |
00214         MPU_REGION_VALID |
00215         MPU_UNPRIVILEGED_RAM_REGION;
00216 
00217     dwRegionAttr = MPU_AP_FULL_ACCESS |
00218         INNER_NORMAL_WB_NWA_TYPE( NON_SHAREABLE ) |
00219         MPU_CalMPURegionSize(MPU_SRAM_UNPRIVILEGE_END_ADDRESS - 
00220                 MPU_SRAM_UNPRIVILEGE_START_ADDRESS) |
00221         MPU_REGION_ENABLE;
00222 
00223     MPU_SetRegion( dwRegionBaseAddr, dwRegionAttr);
00224 
00225     /* SRAM memory privilege region */
00226     dwRegionBaseAddr = MPU_SRAM_PRIVILEGE_START_ADDRESS |
00227         MPU_REGION_VALID |
00228         MPU_PRIVILEGE_RAM_REGION;
00229 
00230     dwRegionAttr = MPU_AP_FULL_ACCESS |
00231         INNER_NORMAL_WB_NWA_TYPE( NON_SHAREABLE ) |
00232         MPU_CalMPURegionSize(MPU_SRAM_PRIVILEGE_END_ADDRESS - 
00233                 MPU_SRAM_PRIVILEGE_START_ADDRESS) |
00234         MPU_REGION_ENABLE;
00235 
00236     MPU_SetRegion( dwRegionBaseAddr, dwRegionAttr);
00237 
00238     /* SRAM memory privilege region */
00239     dwRegionBaseAddr = MPU_SRAM_PRIVILEGE2_START_ADDRESS |
00240         MPU_REGION_VALID |
00241         MPU_PRIVILEGE_RAM_REGION_2;
00242 
00243     dwRegionAttr = MPU_AP_FULL_ACCESS |
00244         INNER_NORMAL_WB_NWA_TYPE( NON_SHAREABLE ) |
00245         MPU_CalMPURegionSize(MPU_SRAM_PRIVILEGE2_END_ADDRESS - 
00246                 MPU_SRAM_PRIVILEGE2_START_ADDRESS) |
00247         MPU_REGION_ENABLE;
00248 
00249     MPU_SetRegion( dwRegionBaseAddr, dwRegionAttr);
00250 
00251     /* Peripheral memory region */
00252     dwRegionBaseAddr = MPU_PERIPHERALS_START_ADDRESS_0 |
00253         MPU_REGION_VALID |
00254         MPU_PERIPHERALS_REGION_0;
00255 
00256     dwRegionAttr = MPU_AP_FULL_ACCESS |
00257         MPU_REGION_EXECUTE_NEVER |
00258         MPU_CalMPURegionSize(MPU_PERIPHERALS_END_ADDRESS_0 - 
00259                 MPU_PERIPHERALS_START_ADDRESS_0) |
00260         MPU_REGION_ENABLE;
00261 
00262     MPU_SetRegion( dwRegionBaseAddr, dwRegionAttr);
00263 
00264     /* Peripheral memory region */
00265     dwRegionBaseAddr = MPU_PERIPHERALS_START_ADDRESS_1 |
00266         MPU_REGION_VALID |
00267         MPU_PERIPHERALS_REGION_1;
00268 
00269     dwRegionAttr = MPU_AP_FULL_ACCESS |
00270         MPU_REGION_EXECUTE_NEVER |
00271         1 << MPU_RASR_SRD_Pos |
00272         MPU_CalMPURegionSize(MPU_PERIPHERALS_END_ADDRESS_1 - 
00273                 MPU_PERIPHERALS_START_ADDRESS_1) |
00274         MPU_REGION_ENABLE;
00275 
00276     MPU_SetRegion( dwRegionBaseAddr, dwRegionAttr);
00277 
00278     /* Sub Peripheral memory region */
00279     dwRegionBaseAddr = MPU_PIOA_PERIPHERALS_REGION_START_ADDRESS |
00280         MPU_REGION_VALID |
00281         MPU_PIOA_REGION_REGION;
00282 
00283     dwRegionAttr = MPU_AP_FULL_ACCESS |
00284         MPU_REGION_EXECUTE_NEVER |
00285         MPU_CalMPURegionSize(MPU_PIOA_PERIPHERALS_REGION_END_ADDRESS - 
00286                 MPU_PIOA_PERIPHERALS_REGION_START_ADDRESS) |
00287         MPU_REGION_ENABLE;
00288 
00289     MPU_SetRegion( dwRegionBaseAddr, dwRegionAttr);
00290 
00291     /* Enable the memory management fault exception */
00292     SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;
00293 
00294     /* Enable the MPU region */
00295     MPU_Enable( MPU_ENABLE | MPU_PRIVDEFENA );
00296 }
00297 
00298 
00299 /**
00300  *  \brief Update MPU regions.
00301  *
00302  *  \return Unused (ANSI-C compatibility).
00303  */
00304 static void _UpdateMPU( uint32_t dwRegionNum, uint32_t dwRegionBaseAddr,
00305                         uint32_t dwRegionAttr)
00306 {
00307     /* Raise privilege, the MPU register could be set only in privilege mode */
00308 
00309     __ASM volatile(" svc 0x00 "); 
00310 
00311     while (!dwRaisePriDone);
00312     dwRaisePriDone = 0;
00313 
00314     /* Disable interrupt */
00315     __disable_irq();
00316 
00317     /* Clean up data and instruction buffer */
00318     __DSB();
00319     __ISB();
00320 
00321     /* Set active region */
00322     MPU_SetRegionNum(dwRegionNum);
00323 
00324     /* Disable region */
00325     MPU_DisableRegion();
00326 
00327     /* Update region attribute */
00328     MPU_SetRegion( dwRegionBaseAddr, dwRegionAttr);
00329 
00330     /* Clean up data and instruction buffer to make the new region taking 
00331            effect at once */
00332     __DSB();
00333     __ISB();
00334 
00335     /* Enable the interrupt */
00336     __enable_irq();
00337 
00338     /* Reset to thread mode */
00339     __set_CONTROL(USER_MODE);
00340 }
00341 
00342 /*----------------------------------------------------------------------------
00343  *        Exported functions
00344  *----------------------------------------------------------------------------*/
00345 
00346 /**
00347  *  \brief Application entry point for MPU example.
00348  *
00349  *  \return Unused (ANSI-C compatibility).
00350  */
00351 extern int main( void )
00352 {
00353     uint8_t ucChoice = 0;
00354 
00355     /* Disable watchdog */
00356     WDT_Disable( WDT ) ;
00357 
00358     uint32_t *pdw = (uint32_t*) MPU_SRAM_PRIVILEGE_START_ADDRESS ;
00359  
00360     /* Output example information */
00361     printf( "\n\r\n\r\n\r" ) ;
00362     printf( "-- MPU Example %s --\n\r", SOFTPACK_VERSION ) ;
00363     printf( "-- %s\n\r", BOARD_NAME ) ;
00364     printf( "-- Compiled: %s %s With %s--\n\r", __DATE__, __TIME__ , COMPILER_NAME) ;
00365 
00366     LED_Configure( LED_YELLOW0 ) ;
00367 
00368     /* Set up the default memory regions */
00369     _SetupMPU();
00370 
00371     /* Set the environment to thread mode */
00372     __set_CONTROL(USER_MODE);
00373 
00374     while (ucChoice != '9') 
00375     {
00376         printf("----------------------------------------\n\r");
00377         printf("    Choose an option below:\n\r");
00378         printf("    1. Protect the Yellow LED region\n\r");
00379         printf("    2. UN-protect the Yellow LED region\n\r");
00380         printf("    3. Toggle the green LED\n\r");
00381         printf("    4. Set the RAM region to read only \n\r");
00382         printf("    5. Set the RAM region to read/write\n\r");
00383         printf("    6. Read the RAM content at offset 0\n\r");
00384         printf("    7. Write the RAM context at offset 0\n\r");
00385         printf("    8. Quit the external program\n\r");
00386         printf("\n\r");
00387         printf("  Choice: ");
00388 
00389         ucChoice = DBG_GetChar();
00390         DBG_PutChar(ucChoice);
00391         printf("\n\r");
00392 
00393         switch (ucChoice) {
00394         case '1':
00395             _UpdateMPU(MPU_PIOA_REGION_REGION,
00396                     MPU_PIOA_PERIPHERALS_REGION_START_ADDRESS |
00397                     MPU_REGION_VALID |
00398                     MPU_PIOA_REGION_REGION,
00399                     MPU_AP_UNPRIVILEGED_READONLY |
00400                     MPU_REGION_EXECUTE_NEVER |
00401                     MPU_CalMPURegionSize(MPU_PIOA_PERIPHERALS_REGION_END_ADDRESS - MPU_PIOA_PERIPHERALS_REGION_START_ADDRESS) |
00402                         MPU_REGION_ENABLE);
00403             break;
00404 
00405         case '2':
00406             _UpdateMPU(MPU_PIOA_REGION_REGION,
00407                     MPU_PIOA_PERIPHERALS_REGION_START_ADDRESS |
00408                     MPU_REGION_VALID |
00409                     MPU_PIOA_REGION_REGION,
00410                     MPU_AP_FULL_ACCESS |
00411                     MPU_REGION_EXECUTE_NEVER |
00412                     MPU_CalMPURegionSize(MPU_PIOA_PERIPHERALS_REGION_END_ADDRESS - MPU_PIOA_PERIPHERALS_REGION_START_ADDRESS) |
00413                     MPU_REGION_ENABLE);
00414             break;
00415 
00416         case '3':
00417         /* Set back to unprivileged mode*/
00418             
00419             LED_Toggle( LED_YELLOW0 ) ;
00420             __set_CONTROL(USER_MODE);
00421             break;
00422 
00423         case '4':
00424             _UpdateMPU(MPU_PRIVILEGE_RAM_REGION,
00425                     MPU_SRAM_PRIVILEGE_START_ADDRESS |
00426                     MPU_REGION_VALID |
00427                     MPU_PRIVILEGE_RAM_REGION,
00428                     MPU_AP_UNPRIVILEGED_READONLY |
00429                     MPU_REGION_CACHEABLE |
00430                     MPU_REGION_BUFFERABLE |
00431                     MPU_TEX_B001|
00432                     MPU_CalMPURegionSize(MPU_SRAM_PRIVILEGE_END_ADDRESS - 
00433                     MPU_SRAM_PRIVILEGE_START_ADDRESS) |
00434                     MPU_REGION_ENABLE);
00435             break;
00436 
00437         case '5':
00438             _UpdateMPU(MPU_PRIVILEGE_RAM_REGION,
00439                     MPU_SRAM_PRIVILEGE_START_ADDRESS |
00440                     MPU_REGION_VALID |
00441                     MPU_PRIVILEGE_RAM_REGION,
00442                     MPU_AP_FULL_ACCESS |
00443                     MPU_REGION_CACHEABLE |
00444                     MPU_REGION_BUFFERABLE |
00445                     MPU_TEX_B001|
00446                     MPU_CalMPURegionSize(MPU_SRAM_PRIVILEGE_END_ADDRESS - 
00447                     MPU_SRAM_PRIVILEGE_START_ADDRESS) |
00448                     MPU_REGION_ENABLE);
00449 
00450             break;
00451 
00452         case '6':
00453             printf("-I- RAM address has content %x \n\r",(unsigned)(pdw[0]));
00454             break;
00455 
00456         case '7':
00457             printf("-I- Write offset 0 of RAM region with content 0x55AA55AA\n\r");
00458             pdw[0] = 0x55AA55AA;
00459             break;
00460 
00461         case '8':
00462             printf("-I- MPU TEST FINISH ...\n\r");
00463             break;
00464             
00465         default:
00466             printf("-I- This option is not valid\n\r");
00467             break;
00468         }
00469     }
00470     /* Setback to privilege mode, before entering the main routine, 
00471        it is supervisor mode*/
00472     __ASM volatile(" svc 0x00 ");
00473     while (!dwRaisePriDone);
00474     dwRaisePriDone = 0;
00475 
00476     __set_CONTROL(PRIVILEGE_MODE);
00477 
00478     return 0;
00479 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines