-/*
+/*
* Application using MF624 UIO driver
- *
- * Copyright (C) 2011 Rostislav Lisovy <lisovy@gmail.com>
- *
+ *
+ * Copyright (C) 2011 Rostislav Lisovy <lisovy@gmail.com>
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
#include <inttypes.h>
#include <unistd.h>
#include <alloca.h>
+#include <stdlib.h>
#include "mf624_SIMULINK.h"
/****************************************************************/
+
+/* Which uio device node to use */
+#define UIO "uio0"
+
mf624_state_t* mfst=NULL;
+unsigned mfst_refcnt = 0;
-int bar_mapping_fill(bar_mapping_t *barmap, const char *uio_dev, int map_nr)
+static int bar_mapping_fill(bar_mapping_t *barmap, const char *uio_dev, int map_nr)
{
FILE *file;
void *s;
return 0;
}
-int bar_mapping_setup(bar_mapping_t *barmap, int device_fd)
+static int bar_mapping_setup(bar_mapping_t *barmap, int device_fd)
{
static size_t page_mask = 0;
off_t mmap_start;
return 0;
}
+static int bar_mapping_destroy(bar_mapping_t *barmap)
+{
+ off_t mmap_start;
+ size_t mmap_size;
+ size_t page_mask = sysconf(_SC_PAGESIZE) - 1;
+
+ mmap_start = barmap->mmap_offset & ~page_mask;
+ mmap_size = barmap->mmap_offset + barmap->size + page_mask - mmap_start;
+ mmap_size &= ~page_mask;
+
+ return munmap(barmap->mmap_addr, mmap_size);
+}
+
/****************************************************************/
#define BUFF_SMALL 32
mf624_state_t mf624_state;
/* Print one byte as binary number */
-void print_8bin(int nr)
+static void print_8bin(int nr)
{
int i;
for (i = 7; i >= 0; i--) {
MFST2REG(mfst, 0, GPIOC_reg));
}
-
+
int DAC_write(mf624_state_t* mfst, dac_channel_t channel, int val)
{
mf624_read16(MFST2REG(mfst, 2, ADSTART_reg));
// Check if conversion has finished
- while((mf624_read32(MFST2REG(mfst, 0, GPIOC_reg)) & GPIOC_EOLC_mask)) {
+ while((mf624_read32(MFST2REG(mfst, 0, GPIOC_reg)) & GPIOC_EOLC_mask)) {
for (i = 0; i < 1000; i++) {} // small wait
}
return 10.0 * ((int16_t) (result << 2)) / (double) 0x8000;
}
+extern uint32_t IRC_mode_change(mf624_state_t* mfst, uint32_t change_mask, uint32_t change_val)
+{
+ /* This sequence should be protected by mutex to protect changes in multirate systems */
+ mfst->IRC_mode = (mfst->IRC_mode & ~change_mask) | (change_val & change_mask);
+ mf624_write32(mfst->IRC_mode, MFST2REG(mfst, 4, IRCCTRL_reg));
+ /*printf("change_mask 0x%08x, change_val 0x%08x\n", change_mask, change_val);*/
+ /*printf("IRC mode set to %08lx\n", mfst->IRC_mode);*/
+ return mfst->IRC_mode;
+}
+
-int open_device(char* path) {
+static int open_device(char* path) {
int device_fd;
device_fd = open(path, O_RDWR | O_SYNC);
if (device_fd == -1) {
- perror("open()");
+ perror(path);
return -1;
}
return device_fd;
}
-void wait_for_interrupts(int device_fd)
+static void wait_for_interrupts(int device_fd)
{
read(device_fd, NULL, 1);
}
-int disable_interrupts(int device_fd)
+static int disable_interrupts(int device_fd)
{
uint32_t control_value = 0;
int status;
return status;
}
-int enable_interrupts(int device_fd)
+static int enable_interrupts(int device_fd)
{
uint32_t control_value = 1;
int status;
return status;
}
-void list_available_mem_regions(char* device)
+static void list_available_mem_regions(char* device)
{
int status;
char path[] = "/sys/class/uio/";
}
-void list_available_io_ports(char *device)
+static void list_available_io_ports(char *device)
{
int status;
char path[] = "/sys/class/uio/";
}
-void run_simple_tests(char* dev_name)
+static void run_simple_tests(char* dev_name)
{
int status;
int device_fd;
if (status != -1) {
printf(" Probably OK\n");
}
-
+
printf("Tring to disable interrupts\n");
status = disable_interrupts(device_fd);
if (status != -1) {
list_available_io_ports(dev_name);
}
-int mmap_regions(mf624_state_t* mfst)
+static int mmap_regions(mf624_state_t* mfst)
{
if (bar_mapping_fill(&mfst->bar0, mfst->uio_dev, 0) < 0) {
fprintf(stderr, "%s bar0 mapping fill failed\n", mfst->uio_dev);
}
+
+/**
+ * Try to initialize the MF624 UIO driver.
+ *
+ * If and only if S is not NULL and initialization fails, then
+ * ssSetErrorStatus() gets called to report the error via Simulink
+ * interface.
+ *
+ * @param S Pointer to SimStruct for error reporting or NULL.
+ *
+ * @return Zero in case of success, -1 in case of error.
+ */
+int mf624_init(SimStruct *S)
+{
+ if (mfst==NULL) {
+ mfst = malloc(sizeof(mf624_state_t));
+ char fn[32];
+ mfst->uio_dev = UIO;
+ snprintf(fn, sizeof(fn), "/dev/%s", mfst->uio_dev);
+
+ mfst->device_fd = open_device(fn);
+ if (mfst->device_fd < 0) {
+ if (S) ssSetErrorStatus(S,"/dev/" UIO ": open failed");
+ goto free;
+ }
+ if (mmap_regions(mfst) < 0) {
+ if (S) ssSetErrorStatus(S,"/dev/" UIO ": mmap_regions failed");
+ goto close;
+ }
+ }
+ mfst_refcnt++;
+ return 0;
+close:
+ close(mfst->device_fd);
+free:
+ free(mfst);
+ mfst = NULL;
+ return -1;
+}
+
+int mf624_done()
+{
+ if (mfst) {
+ if (--mfst_refcnt == 0) {
+ close(mfst->device_fd);
+ bar_mapping_destroy(&mfst->bar0);
+ bar_mapping_destroy(&mfst->bar2);
+ bar_mapping_destroy(&mfst->bar4);
+ free(mfst);
+ mfst = NULL;
+ }
+ }
+
+ return 0;
+}
+
+
+/**
+ * Check whether MF624 card is initialized.
+ *
+ * @param S
+ *
+ * @return Zero if MF624 is initialized, -1 othewise.
+ */
+int mf624_check(SimStruct *S)
+{
+ if (mfst==NULL) {
+ if (S) ssSetErrorStatus(S, "MF624 is not initialized");
+ return -1;
+ }
+ else
+ return 0;
+}
+
/*int main(int argc, char* argv[])
{
mf624_state_t* mfst = &mf624_state;
printf("Setting DA1 to 5 V\n");
DAC_write(mfst, DA1, 0x3000);
sleep(1);
-
+
printf("Reading ADC0: ");
printf("%f V\n", ADC_read(mfst, AD0));
sleep(1);