(ES) 3.3.1 Aplicaciones de.espacio de usuario (User space) - coffeebrain/Codesign_HW_SW GitHub Wiki

Key concepts used in this section

For this section it is important to know the following key concepts:

Is the system of memory allocation used to run applications.


Memory mapping

HPS header file

Creating hps_0.h

  1. Start an Embedded Command Shell
~/intelFPGA/19.1/embedded/embedded_command_shell.sh
  1. Add sopc_builder binary files to the PATH environment variable
export PATH=$PATH:~/intelFPGA_lite/19.1/quartus/sopc_builder/bin
  1. Go to userspace folder in the project folders
cd ~/Codesign_HW_SW/software/userspace
  1. Run the sopc-create-header-files command with the following arguments
sopc-create-header-files ../../Quartus_Files/soc_system.sopcinfo --single hps_0.h --module hps_0
  1. A file name hps_0.h must have been created in the userspace folderm the file should look something like this
#ifndef _ALTERA_HPS_0_H_
#define _ALTERA_HPS_0_H_
...
#define ONCHIP_MEMORY2_0_COMPONENT_TYPE altera_avalon_onchip_memory2
#define ONCHIP_MEMORY2_0_COMPONENT_NAME onchip_memory2_0
...
#define CUSTOM_COMPONENT_0_COMPONENT_TYPE custom_component
#define CUSTOM_COMPONENT_0_COMPONENT_NAME custom_component_0
#define CUSTOM_COMPONENT_0_BASE 0x10000
#define CUSTOM_COMPONENT_0_SPAN 8
#define CUSTOM_COMPONENT_0_END 0x10008
...

User space app creation

Make devmem_custom_component.c and Makefile files.

Making Makefile

COMPONENT = custom_component
TARGET = devmem_$(COMPONENT)

CFLAGS = -static -g -Wall -std=gnu99
LDFLAGS = -g -Wall
CC = $(CROSS_COMPILE)gcc
ARCH = arm
HOST = <DE0-Nano-SoC-IP-address>

build: $(TARGET)
$(TARGET): $(TARGET).o
	$(CC) $(LDFLAGS) $^ -o $@

%.o: %.c
	$(CC) $(CFLAGS) -c $< -o $@

.PHONY: clean
clean:
	rm -f $(TARGET) *.a *.o *.~

install: $(TARGET)
	scp $(TARGET) root@${HOST}:/root/$(COMPONENT)

Making C source file devmem_custom_component.c

To make a user space application that interacts with an IP component the following code sections must be taken into consideration:

  1. Including important Libraries
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <error.h>
#include <stdint.h>
#include <sys/mman.h>
  1. Define Lightweight bridge memory base address and span
#define HPS_TO_FPGA_LW_BASE 0xFF200000
#define HPS_TO_FPGA_LW_SPAN 0x0020000
  1. Create neccessary variable, for example an int variable to save a read value
int custom_component_0_value = 0;
  1. Use the open command from fcntl.h header file to call the /dev/mem device and be sure it opens by assuring a major number greater than 0 is given
devmem_fd = open("/dev/mem", O_RDWR | O_SYNC);
if(devmem_fd < 0)
{
	perror("devmem open");
	exit(EXIT_FAILURE);
}
  1. Map the entire address space of the Lightweight bridge with mmap() to use access later with the custom module and be sure it doesn't fail
lw_bridge_map = (uint32_t*)mmap(NULL, HPS_TO_FPGA_LW_SPAN, PROT_READ|PROT_WRITE, MAP_SHARED, devmem_fd, HPS_TO_FPGA_LW_BASE); 
if(lw_bridge_map == MAP_FAILED) 
{ 
	perror("devmem mmap"); 
	close(devmem_fd); 
	exit(EXIT_FAILURE); 
}
  1. Map the custom module with its corresponding offset from the Lightweight bridge base address
custom_component_map = (uint32_t*)(lw_bridge_map + CUSTOM_COMPONENT_0_BASE);
  1. Perform write or read operations on the custom_component_map
  • Read from the custom_component_map memory address, for example in the address 0
custom_component_0_value = (int) custom_component_map[0];
  • Write to the custom_component_map memory address, for example a 0xFF
*custom_component_map = 0xFF;
  1. Unmap lw_bridge_map
result = munmap(lw_bridge_map, HPS_TO_FPGA_LW_SPAN); 
if(result < 0)
{
	perror("devmem munmap");
	close(devmem_fd);
	exit(EXIT_FAILURE);
}
  1. Close the file descriptor from the /dev/mem device and exit user space app
close(devmem_fd);
exit(EXIT_SUCCESS);

Complete code

#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <error.h>
#include <stdint.h>
#include <sys/mman.h>
// Lightweight bridge memory base address and span
#define HPS_TO_FPGA_LW_BASE 0xFF200000
#define HPS_TO_FPGA_LW_SPAN 0x0020000
int main(int argc, char ** argv)
{
	int custom_component_0_value = 0;
	// Open memory device
	devmem_fd = open("/dev/mem", O_RDWR | O_SYNC);
	if(devmem_fd < 0)
	{
		perror("devmem open");
		exit(EXIT_FAILURE);
	}
	// Map lightweight bridge memory
	lw_bridge_map = (uint32_t*)mmap(NULL, HPS_TO_FPGA_LW_SPAN, PROT_READ|PROT_WRITE, MAP_SHARED, devmem_fd, HPS_TO_FPGA_LW_BASE); 
	if(lw_bridge_map == MAP_FAILED) 
	{ 
		perror("devmem mmap"); 
		close(devmem_fd); 
		exit(EXIT_FAILURE); 
	}
	// Map component. Lightweight bridge + Component offset
	custom_component_map = (uint32_t*)(lw_bridge_map + CUSTOM_COMPONENT_0_BASE);
	// Read from custom component
	custom_component_0_value = (int) custom_component_map[0];
	// Write to custom component
	*custom_component_map = 0xFF;
	// Unmap lightweight bridge memory
	result = munmap(lw_bridge_map, HPS_TO_FPGA_LW_SPAN); 
	if(result < 0)
	{
		perror("devmem munmap");
		close(devmem_fd);
		exit(EXIT_FAILURE);
	}
	// Close and exit
	close(devmem_fd);
	exit(EXIT_SUCCESS);
}
⚠️ **GitHub.com Fallback** ⚠️