Introduction This example design shows how to implement the HPS SDRAM memory protection rules via an unhosted Baremetal application. The rules are tested using the included System Console Toolkit. This project can be booted from SD/MMC. Note: This example was tested against SoC EDS 15.1b185. ==== Target Boards: - Altera Cyclone V SoC Development Board Rev D - Terasic Atlas SoC Kit ==== Notes: - This example was developed with and tested against SoC EDS 15.1b185. - The example requires the preloader to set up the UART appropriately (baud rate, parity, stop bits). - Two preloaders are available for this example, one for each of the target boards. The following settings were used to compile the preloaders. preloader-mkpimage_cv_dev_kit.bin: - BOOT_FROM_SDMMC: checked - FAT_SUPPORT: unchecked - WATCHDOG_ENABLE: unchecked - SDRAM_SCRUBBING: checked - SDRAM_SCRUB_REMAINING_REGION: checked preloader-mkpimage_atlas.bin: - BOOT_FROM_SDMMC: checked - FAT_SUPPORT: unchecked - WATCHDOG_ENABLE: unchecked - SDRAM_SCRUBBING: unchecked - SDRAM_SCRUB_REMAINING_REGION: unchecked Pre-compiled files for each of the preloaders are provided with the project. Simply use the preloader that matches the board you are using. ===== Source Files The following are descriptions of the relevant files and folders contained in this project: main.c Contains the main function, which enables error handling, enables the F2H bridge, configures memory protection rules, and runs a UI loop. io.c Contains the low-level I/O functions required by the compilerto implement a very basic output over UART. cycloneV-dk-ram-modified.ld The linker script, which is based on the default linker script shipped with SoC EDS. The linker script was modified to free 64 bytes at the beginning of the SDRAM window to make room for the preloader to place the mkimage signature in SDRAM. Additionally, the linker script loads the Baremetal application into the privileged section of memory (HPS access only). test_trustzone.c Contains the function calls necessary to write, read, and print the memory protection rules. utility.s Assembler source file – required for error handling. ===== Building the Example Before running the example, the target executable must first be built. 1. Enter the Embedded Command Shell a. Navigate to the project directory (If using Windows, ensure there are no spaces in any of the directory names) b. Enter “make”to build the necessary files The Command Shell should detail the progress of the build and report any warnings or errors. Sample output: arm-altera-eabi-as -march=armv7-a -mcpu=cortex-a9 -c utility.s -o utility.o arm-altera-eabi-gcc -g -O0 -Wall -std=c99 -mcpu=cortex-a9 -mfloat-abi=softfp -mfpu=neon -IC:/altera/15.1/embedded/ip/altera/hps/altera_hps/hwlib/include -IC:/altera/15.1/embedded/ip/altera/hps/altera_hps/hwlib/include/soc_cv_av -Dsoc_cv_av -c test_trustzone.c -o test_trustzone.o arm-altera-eabi-gcc -g -O0 -Wall -std=c99 -mcpu=cortex-a9 -mfloat-abi=softfp -mfpu=neon -IC:/altera/15.1/embedded/ip/altera/hps/altera_hps/hwlib/include -IC:/altera/15.1/embedded/ip/altera/hps/altera_hps/hwlib/include/soc_cv_av -Dsoc_cv_av -c main.c -o main.o main.c: In function 'read': main.c:147:4: warning: format '%p' expects argument of type 'void *', but argument 3 has type 'unsigned int' [-Wformat=] printf("The value at address %p is %p.\r\n",read_data ,*read_data); ^ main.c:147:4: warning: format '%p' expects argument of type 'void *', but argument 3 has type 'unsigned int' [-Wformat=] main.c: In function 'write': main.c:183:4: warning: format '%p' expects argument of type 'void *', but argument 2 has type 'unsigned int' [-Wformat=] printf("You have written %p to location %p.\r\n", *write_data, write_data); ^ main.c:183:4: warning: format '%p' expects argument of type 'void *', but argument 2 has type 'unsigned int' [-Wformat=] arm-altera-eabi-gcc -g -O0 -Wall -std=c99 -mcpu=cortex-a9 -mfloat-abi=softfp -mfpu=neon -IC:/altera/15.1/embedded/ip/altera/hps/altera_hps/hwlib/include -IC:/altera/15.1/embedded/ip/altera/hps/altera_hps/hwlib/include/soc_cv_av -Dsoc_cv_av -c io.c -o io.o arm-altera-eabi-g++ -TcycloneV-dk-ram-modified.ld -mcpu=cortex-a9 -mfloat-abi=softfp -mfpu=neon test_trustzone.o main.o io.o utility.o -o test_trustzone.axf arm-altera-eabi-objcopy -O binary test_trustzone.axf test_trustzone.bin mkimage -A arm -T standalone -C none -a 0x100040 -e 0 -n "baremetal image" -d test_trustzone.bin test_trustzone-mkimage.bin Image Name: baremetal image Created: Sun Mar 27 15:49:39 2016 Image Type: ARM Linux Standalone Program (uncompressed) Data Size: 45808 Bytes = 44.73 kB = 0.04 MB Load Address: 00100040 Entry Point: 00000000 ===== System Setup 1. Copy the hps_sdram_protection_toolkit into the following directory: “altera//quartus/sopc_builder/system_console/toolkits” 2. Connect the UART port on the dev kit to the host computer. 3. Connect the USB-BlasterII to the host computer. 5. Install the USB-BlasterII driver on the host computer if that driver is not already present. Consult documentation for QuartusII for instructions on installing the USB-BlasterII driver. 6. Enter the Embedded Command Shell and launch system console. 7. Select load project and navigate to the QPF of the appropriate GHRD. 8. Right click on devices and select program SOF. 9. Once the device has been programmed, launch the HPS SDRAM Memory Protection Toolkit ===== Booting the Example from SD/MMC 1. Write the bootable SD image to an SD card. You can for example use the file \embedded\embeddedsw\socfpga\prebuilt_images\sd_card_linux_boot_image.tar.gz. 2. Write the appropriate preloader to the A2 partition on the SD Card. The command is “sudo dd if=preloader-mkpimage_cv_dev_kit.bin of=/dev/ bs=64k seek=0” **WARNING: Ensure you are writing to the correct device. Improper use of the dd command can destroy information on your hard drive.** 3.Write the application image file test-trustzone-mkimage.bin to the A2 partition on the SD card – Example command “sudo dd if=test-trustzone-mkimage.bin of=/dev/mmcblk0p3 bs=64k seek=4” **WARNING: Ensure you are writing to the correct device. Improper use of the dd command can destroy information on your hard drive.** 4. Configure the BSEL pins to boot from SD/MMC 5. Connect the USB-to-serial bridge to the host computer. 6. Start the serial terminal on the host computer, use 115,200-8-N-1 and connect to the board. 7. Power up (or reset) the board 8. Connect an additional USB to the USB-BlasterII port on the dev kit 9. Launch System Console from the embedded command shell command: system-console. 10. Select Load Design and target the QPF in the GHRD Folder. The GHRD for Cyclone V Dev kit can be found in /embedded/examples/hardware/cv_soc_devkit_ghrd. The GHRD for the Terasic board can be found in the system CD in the Demonstrations/SoC_FPGA/DE0_NANO_SOC_GHRD directory. The link to download the system CD is http://www.terasic.com/downloads/cd-rom/de0-nano-soc/DE0-Nano-SoC_v.1.1.0_SystemCD.zip 11. Program the FPGA via system console (right click the device and select program SOF. 12. Launch the HPS SDRAM Memory Protection Toolkit 13. Select OpenMaster to ensure the system console is able to properly communicate with the HPS. 14. Follow the instructions shown in the terminal. The access ranges are indicated below. All addresses must end in 0,4,8,C as misaligned access will result in an error. All user input is performed via system console. The write address command writes 32bits at a time. The write data command writes 1 byte (8 bits) of data at a time (0-F). The program is not set up to write 0s. A zero in the register is treated as a null and no action is taken. 15. HPS Read 15.a In order to perform a read on the HPS side enter a '1' at address location 0x1FFFFFF4 (Enter 0x1 in the Write Data, Data cell, then enter Write Data. The correct address should be auto populated) 15.b Next enter a 32bit address in the write address data cell (example address: 0x1FFF4444) once the address is written the data will be printed out via UART. 16. HPS Write 16.a In order to perform a write on the HPS side enter a '2' at address location 0x1FFFFFF4 (Enter 0x2 in the Write Data, Data cell, then click "Write data") 16.b Next enter a 32bit address you wish to write to in the Write address data cell (example address: 0x1FFF4444) 16.c Next write a 8bit piece of data you wish to write. Enter the data in the write data, data cell. (Example data: 0xA). Make sure you change the address being targeted in the Write data address cell to 0x1FFFFFD4 17. System Console Read (Read through L3 Interconnect) 17.a Enter the address you wish to read from in the Read address cell (Is prepopulated to address 0x1FFFFFF4) 17.b Select the Read button - the results will be output in the data cell on the far right (It is important to note that read attempts to restricted address will return NULL or all 0's) 18. System Console Write (Write through L3 Interconnect) 18.a You can perform 32bit or 8bit writes by using the Write data or Write address buttons located in the Write Command section. 18.b Enter the address you wish to write to in the Write data or Write address, address cell 18.c Enter the data you wish to write in the corresponding data cell 18.d Select the Write data/Write address button to write the data. (Write requests to protected locations will not result in any error flags being thrown - the values in memory will simply not be changed. To confirm this perform an HPS Read on the desired location) HPS Access Range: 0x00000000 – 0x1FFFFFFF L3 Access Range: 0x13F80000 – 0x3FF00000 Shared Access Range: 0x13F80000 – 0x1FFFFFFF =====