X-Git-Url: http://rtime.felk.cvut.cz/gitweb/mf624-simulink.git/blobdiff_plain/ec8724249fe0534577a38c2ae001adcdbcea3bb7..b97abaaa4663e5a6caa3af4f65a09c5ca96b7e2e:/mf624_SIMULINK.c diff --git a/mf624_SIMULINK.c b/mf624_SIMULINK.c index 30f3e96..ebd2276 100644 --- a/mf624_SIMULINK.c +++ b/mf624_SIMULINK.c @@ -1,8 +1,8 @@ -/* +/* * Application using MF624 UIO driver - * - * Copyright (C) 2011 Rostislav Lisovy - * + * + * Copyright (C) 2011 Rostislav Lisovy + * * 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 @@ -31,14 +31,20 @@ #include #include #include +#include #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; @@ -82,7 +88,7 @@ int bar_mapping_fill(bar_mapping_t *barmap, const char *uio_dev, int map_nr) 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; @@ -106,6 +112,19 @@ int bar_mapping_setup(bar_mapping_t *barmap, int device_fd) 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 @@ -119,7 +138,7 @@ int bar_mapping_setup(bar_mapping_t *barmap, int device_fd) 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--) { @@ -150,7 +169,7 @@ void DAC_enable(mf624_state_t* mfst) MFST2REG(mfst, 0, GPIOC_reg)); } - + int DAC_write(mf624_state_t* mfst, dac_channel_t channel, int val) { @@ -187,7 +206,7 @@ double ADC_read(mf624_state_t* mfst, adc_channel_t channel) 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 } @@ -197,25 +216,35 @@ double ADC_read(mf624_state_t* mfst, adc_channel_t channel) 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; @@ -229,7 +258,7 @@ int disable_interrupts(int device_fd) return status; } -int enable_interrupts(int device_fd) +static int enable_interrupts(int device_fd) { uint32_t control_value = 1; int status; @@ -243,7 +272,7 @@ int enable_interrupts(int device_fd) return status; } -void list_available_mem_regions(char* device) +static void list_available_mem_regions(char* device) { int status; char path[] = "/sys/class/uio/"; @@ -279,7 +308,7 @@ void list_available_mem_regions(char* device) } -void list_available_io_ports(char *device) +static void list_available_io_ports(char *device) { int status; char path[] = "/sys/class/uio/"; @@ -321,7 +350,7 @@ void list_available_io_ports(char *device) } -void run_simple_tests(char* dev_name) +static void run_simple_tests(char* dev_name) { int status; int device_fd; @@ -340,7 +369,7 @@ void run_simple_tests(char* dev_name) if (status != -1) { printf(" Probably OK\n"); } - + printf("Tring to disable interrupts\n"); status = disable_interrupts(device_fd); if (status != -1) { @@ -356,7 +385,7 @@ void run_simple_tests(char* dev_name) 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); @@ -402,6 +431,80 @@ int mmap_regions(mf624_state_t* mfst) } + +/** + * 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; @@ -458,7 +561,7 @@ int mmap_regions(mf624_state_t* mfst) 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);