#define _BSD_SOURCE
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdint.h>
#define HK_FPGA_BASE_ADDR 0x40000000
#define HK_FPGA_BASE_SIZE 0x30000
#define LED_CONTROL_OFFSET 0x30
uint32_t *g_hk_fpga_reg_mem = NULL;
uint32_t *g_hk_fpga_LED_mem = NULL;
/** The memory file descriptor used to mmap() the FPGA space */
int g_hk_fpga_mem_fd = -1;
inline void toggle_led(const uint32_t led_pin);
int __hk_fpga_cleanup_mem(void);
int __hk_fpga_cleanup_mem(void) {
/* If register structure is NULL we do not need to un-map and clean up */
if(g_hk_fpga_reg_mem) {
if(munmap(g_hk_fpga_reg_mem, HK_FPGA_BASE_SIZE) < 0) {
return -1;
}
g_hk_fpga_reg_mem = NULL;
if(g_hk_fpga_LED_mem)
g_hk_fpga_LED_mem = NULL;
}
if(g_hk_fpga_mem_fd >= 0) {
close(g_hk_fpga_mem_fd);
g_hk_fpga_mem_fd = -1;
}
return 0;
}
void toggle_led(const uint32_t led_pin) {
*g_hk_fpga_LED_mem ^= 1 << led_pin;
}
int main() {
/* Page variables used to calculate correct mapping addresses */
void *page_ptr;
long page_addr, page_off, page_size = sysconf(_SC_PAGESIZE);
/* If module was already initialized, clean all internals */
if(__hk_fpga_cleanup_mem() < 0) {
return -1;
}
/* Open /dev/mem to access directly system memory */
g_hk_fpga_mem_fd = open("/dev/mem", O_RDWR | O_SYNC);
if(g_hk_fpga_mem_fd < 0) {
return -1;
}
/* Calculate correct page address and offset from HK_FPGA_BASE_ADDR and
* HK_FPGA_BASE_SIZE
*/
page_addr = HK_FPGA_BASE_ADDR & (~(page_size-1));
page_off = HK_FPGA_BASE_ADDR - page_addr;
/* Map FPGA memory space to page_ptr. */
page_ptr = mmap(NULL, HK_FPGA_BASE_SIZE, PROT_READ | PROT_WRITE,
MAP_SHARED, g_hk_fpga_mem_fd, page_addr);
if((void *)page_ptr == MAP_FAILED) {
__hk_fpga_cleanup_mem();
return -1;
}
/* Set FPGA HK module pointers to correct values. */
g_hk_fpga_reg_mem = page_ptr + page_off;
g_hk_fpga_LED_mem = g_hk_fpga_reg_mem + (LED_CONTROL_OFFSET / sizeof(uint32_t));
for (int i = 0; i < 20; i++) {
toggle_led(3);
usleep(200000);
}
return 0;
}