Using Linux with ARM Tutorial #3
Why use an Operating System? USB Device Drivers Keyboard, Mouse, Bluetooth Internet Stack Easily start using the Ethernet port Multi-threaded Applications
But Maybe an Operating System is Overkill If only limited OS features are required Use ARM Semihosting
Hands-on Session Learn about Semihosting functions
Exercise 6: Semihosting Virtual Operating System Allows C programs to make system calls I/O functions Time functions File operations Altera Monitor Program supports a subset printf and scanf to and from the terminal window. Some time functions
Printf, scanf and time functions Program Printf, scanf and time functions #include <stdio.h> #include <time.h> int main(void)( char str[64]; int age = 0; // Get the initial timestamp clock_t start_time = clock(); while(1){ printf("What is your name?\n"); scanf("%s",str); printf("What is your age?\n"); scanf("%d",&age); ... } return 0;
Step 1: Create a New Project Sets up the Altera Monitor Program Select files to work with Specify target system
Step 1.1: Specify name, directory and architecture
Step 1.2: Select the DE1-SoC Computer System
Step 1.3: Select Program Type and Sample Program
Step 1.4: Automatically Includes Example’s Source Files
Step 1.5: Set Board Connection and Select Processor
Step 1.6: Leave Default Memory Settings
Step 2: Program the FPGA with the Computer System
Step 3: Compile and Load Compile your C language program Load the compiled code into the memory on the DE1-SoC board
Step 4: Run
Step 5: Type in your name
Step 6: Type in your age
Step 7: See the Result of the Semi-hosting Functions
Step 8: Open the Sample Code
Please read the instructions at Hands-on Session Please read the instructions at “/exercise6/instructions.pdf”
Boot Sequence with Altera Monitor Program Resets the HPS Halts the code in the Boot ROM Loads a preloader into the HPS on-chip RAM Preloader comes pre-compiled with the Monitor Program Initializes the DDR3 SDRAM and HPS I/O pins Enables the HPS-FPGA bridges Disables the watchdog timers Re-maps the DDR3 SDRAM to address 0x00000000 Loads the user’s code into the DDR3 SDRAM Pauses the processor at the first instruction
Typical ARM Cortex-A9 Boot Sequence Boot ROM Hard coded by Altera Determines the boot source by reading the boot select pins Preloader In Flash/SD Card or FPGA Typically initializes the DDR3 SDRAM and HPS I/O pins Boot loader Loads and starts the operating system
We provide premade SD Card Images Linux SD Card Images We provide premade SD Card Images Preloader, Boot Loader, Linux (Kernel + Distro) FPGA related drivers Automatically programs FPGA with prebuilt system We have: Command-line GUI (Ubuntu)
Hands-on Session Boot Linux Connect to Linux via USB-to-UART and Putty Compile and run a simple program
Exercise 7: Talking to Linux on the DE1-SoC Compile and execute the “Hello World” program #include <stdio.h> int main(void){ printf("Hello World!\n"); return 0; }
Step 1: Power Off the DE1-SoC
Step 2: Set MSEL to `b01010 on the DE1-SoC Enables ARM to be able to configure the FPGA
Step 3: Insert Linux SD Card
Step 4: Power On the DE1-SoC
Step 5: Ensure the UART-to-USB is Connected to the Host Computer
Step 6: Check Device Manager for COM Port Settings
Step 7: Open Putty
Step 8: Select ‘Serial’ Connection Type
Step 9: Enter COM Port Name in ‘Serial line’ Box
Step 10: Enter Serial Port Settings as shown
Step 11: Save Session for Later Use
Step 12: Open Connection
Step 13: In Putty: Change to the Example Directory
Step 14: Compile the Sample Program
Step 15: Execute the Sample Program
Step 16: See the Output
Please read the instructions at Hands-on Session Please read the instructions at “/exercise7/instructions.pdf”
What if We Want to Communicate with the FPGA?
Copy the programming bitstream to Linux Then within Linux command line Programming the FPGA Create the desired system using the Quartus II software and the Qsys System Integration Tool Copy the programming bitstream to Linux Then within Linux command line Disable the HPS-FPGA bridges Configure the FPGA with your bitstream Re-enable the bridges
The Default DE1-SoC Computer System The Linux distribution automatically programs the FPGA with the DE1-SoC Computer System during boot
Virtual Addresses vs Physical Addresses Linux creates a virtual address space for programs FPGA peripheral are given physical addresses in Qsys Linux provides the function ‘mmap’ to map virtual address space to physical addresses ‘munmap’ un-maps addresses
Hands-on Session Communicate with FPGA peripheral within Linux
Exercise 8: Using FPGA Peripherals within Linux We will use the default DE1-SoC Computer system We will use the red LEDs and the slider switches The program copies the value of the switches to the LEDs
MMAP #define HW_REGS_BASE ( 0xff200000 ) #define HW_REGS_SPAN ( 0x00200000 ) #define HW_REGS_MASK ( HW_REGS_SPAN - 1 ) // Open /dev/mem if( ( fd = open( "/dev/mem", ( O_RDWR | O_SYNC ) ) ) == -1 ) { printf( "ERROR: could not open \"/dev/mem\"...\n" ); return( 1 ); } // get virtual addr that maps to physical virtual_base = mmap( NULL, HW_REGS_SPAN, ( PROT_READ | PROT_WRITE ), MAP_SHARED, fd, HW_REGS_BASE ); if( virtual_base == MAP_FAILED ) { printf( "ERROR: mmap() failed...\n" ); close( fd ); return(1);
Using the Virtual Address #define LED_PIO_BASE 0x0 #define SW_PIO_BASE 0x40 volatile unsigned int *h2p_lw_led_addr=NULL; volatile unsigned int *h2p_lw_sw_addr=NULL; // Get the address that maps to the LEDs h2p_lw_led_addr=(unsigned int *)(virtual_base + (( LED_PIO_BASE ) & ( HW_REGS_MASK ) )); h2p_lw_sw_addr=(unsigned int *)(virtual_base + (( SW_PIO_BASE ) & ( HW_REGS_MASK ) )); while(!stop){ *h2p_lw_led_addr = *h2p_lw_sw_addr; }
MUNMAP if( munmap( virtual_base, HW_REGS_SPAN ) != 0 ) { printf( "ERROR: munmap() failed...\n" ); close( fd ); return( 1 ); }
Step 1: Open the Connection to the DE1-SoC using Putty
Step 2: Change to the Example Directory
Step 3: Compile the Sample Program
Step 4: Execute the Sample Program
Step 5: The Program is Running. Try Toggling the Switches.
Step 6: Press Control-C to Exit the Program
Step 7: Open the leds.c file. See the mmap usage.
Please read the instructions at Hands-on Session Please read the instructions at “/exercise8/instructions.pdf”
Handling Interrupts from FPGA Peripherals This requires a Linux device driver A. Modify the Linux kernel B. Write a kernel module Kernel modules can be loaded at run-time Easily register interrupt handler using library functions
Interrupt handling (optional) Exit routine Kernel Modules Initialization Sets up the module upon loading Interrupt handling (optional) Exit routine Clears used resources upon unloading
Hands-on Session Create a Linux device driver
Exercise 8: Creating a Linux Device Driver We will use the red LEDs and pushbuttons The program increments the value displayed on the LEDs when a pushbutton is pressed
Kernel Module - Initialization void * lwbridgebase; static int __init intitialize_pushbutton_handler(void) { // get the virtual addr that maps to 0xff200000 lwbridgebase = ioremap_nocache(0xff200000, 0x200000); // Set LEDs to 0x200 (the leftmost LED will turn on) iowrite32(0x200,lwbridgebase); // Clear the PIO edgecapture register (clear any pending interrupt) iowrite32(0xf,lwbridgebase+0x5c); // Enable IRQ generation for the 4 buttons iowrite32(0xf,lwbridgebase+0x58); // Register the interrupt handler. return request_irq(73, (irq_handler_t)irq_handler, IRQF_SHARED, "pushbutton_irq_handler", (void *)(irq_handler)); } module_init(intitialize_pushbutton_handler);
Kernel Module – Interrupt Handler irq_handler_t irq_handler(int irq, void *dev_id, struct pt_regs *regs) { // Increment the value on the LEDs iowrite32(ioread32(lwbridgebase)+1,lwbridgebase); // Clear the edgecapture register (clears current interrupt) iowrite32(0xf,lwbridgebase+0x5c); return (irq_handler_t) IRQ_HANDLED; }
Kernel Module – Exit Routine static void __exit cleanup_pushbutton_handler(void) { // Turn off LEDs and de-register irq handler iowrite32(0x0,lwbridgebase); free_irq(73, (void*) irq_handler); } module_exit(cleanup_pushbutton_handler);
Step 1: Open the Connection to the DE1-SoC using Putty
Step 2: Change to the Example Directory
Step 3: Compile the Sample Program
Step 4: Compilation Complete
Step 5: Insert Newly Compiled Kernel Module into Linux
Step 6: Run ‘lsmod’ to See All Loaded Kernel Modules
Step 6: The Pushbutton IRQ Handler was Loaded
Step 7: Try Toggling the Pushbuttons
Step 8: Remove the Kernel Module
Step 9: Run ‘lsmod’ to See All Loaded Kernel Modules
Step 10: Examine the ‘pushbutton_irq_handler.c’ file
Please read the instructions at Hands-on Session Please read the instructions at “/exercise9/instructions.pdf”
Where did we go from here? Summary #4 What did we learn? Using semi-hosting ARM Cortex-A9 Boot Sequence How to run the Linux operating system How to communicate between the HPS and FPGA under Linux How to create a kernel module Where did we go from here? Tutorials: Using Linux on the DE1-SoC Using Terminals with DE-Series Boards SD Card images Linux for the DE1-SoC Tons of Linux documentation online http://university.altera.com