]> rtime.felk.cvut.cz Git - mf6xx.git/commitdiff
Cleanup of MF624 UIO code to work with recent Linux kernels.
authorPavel Pisa <pisa@cmp.felk.cvut.cz>
Fri, 24 May 2013 13:12:42 +0000 (15:12 +0200)
committerPavel Pisa <pisa@cmp.felk.cvut.cz>
Fri, 24 May 2013 13:12:42 +0000 (15:12 +0200)
Tested on 3.2.41 kernel on AMD64 Debian.

Signed-off-by: Pavel Pisa <pisa@cmp.felk.cvut.cz>
src/uio/mf624/userspace/test_application/main.c [changed mode: 0755->0644]

old mode 100755 (executable)
new mode 100644 (file)
index 401fa30..321a22e
 #include <sys/types.h>
 #include <sys/mman.h>
 #include <stdint.h> // uintX_t
+#include <inttypes.h>
 #include <unistd.h>
+#include <alloca.h>
+
+/****************************************************************/
+
+typedef struct bar_mapping_t {
+       uintptr_t virt_addr;
+       void *    mmap_addr;
+       uintptr_t phys_addr;
+       uint32_t  size;
+       uint32_t  offset;
+} bar_mapping_t;
+
+int bar_mapping_fill(bar_mapping_t *barmap, const char *uio_dev, int map_nr)
+{
+       FILE *file;
+       void *s;
+       int ssiz;
+       ssiz = snprintf(NULL, 0, "/sys/class/uio/%s/maps/map%i/", uio_dev, map_nr);
+       if (ssiz < 0)
+               return -1;
+       /* add reserve to store each size addr, name, offset, size */
+        ssiz += 6 + 1;
+       s = alloca(ssiz + 6 + 1);
+
+       snprintf(s, ssiz, "/sys/class/uio/%s/maps/map%i/addr", uio_dev, map_nr);
+       file = fopen(s, "rb");
+       fscanf(file, "%"SCNiPTR, &barmap->phys_addr);
+       fclose(file);
+
+       snprintf(s, ssiz, "/sys/class/uio/%s/maps/map%i/offset", uio_dev, map_nr);
+       file = fopen(s, "rb");
+       fscanf(file, "%"SCNi32, &barmap->offset);
+       fclose(file);
+
+       snprintf(s, ssiz, "/sys/class/uio/%s/maps/map%i/size", uio_dev, map_nr);
+       file = fopen(s, "rb");
+       fscanf(file, "%"SCNi32, &barmap->size);
+       fclose(file);
+
+       return 0;
+}
+
+int bar_mapping_setup(bar_mapping_t *barmap, int device_fd)
+{
+       static size_t page_mask = 0;
+       off_t mmap_offset;
+        size_t mmap_size;
+
+       if (!page_mask)
+                page_mask = sysconf(_SC_PAGESIZE) - 1;
+
+       mmap_offset = barmap->offset & ~page_mask;
+        mmap_size = barmap->offset + barmap->size + page_mask - mmap_offset;
+       mmap_size &= ~page_mask;
+
+       barmap->mmap_addr = mmap(0, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, device_fd, mmap_offset);
+       if (barmap->mmap_addr == MAP_FAILED) {
+               return -1;
+       }
+
+       barmap->virt_addr = (uintptr_t)barmap->mmap_addr;
+       barmap->virt_addr += barmap->offset & page_mask;
+
+       return 0;
+}
+
+/****************************************************************/
 
 #define BUFF_SMALL             32
 #define BUFF_MID               256
 #define DA6_reg                        0x2C
 #define DA7_reg                        0x2E
 
-
-
 #define GPIOC_DACEN_mask       (1 << 26)
-#define GPIOC_LDAC_mask                (1 << 23)       
+#define GPIOC_LDAC_mask                (1 << 23)
 #define GPIOC_EOLC_mask                (1 << 17)
 
-#define BAR0_offset            (0 * sysconf(_SC_PAGESIZE))
-#define BAR2_offset            (1 * sysconf(_SC_PAGESIZE))
-#define BAR4_offset            (2 * sysconf(_SC_PAGESIZE))
-
 
 typedef enum {DA0, DA1, DA2, DA3, DA4, DA5, DA6, DA7} dac_channel_t;
 typedef enum {AD0, AD1, AD2, AD3, AD4, AD5, AD6, AD7} adc_channel_t;
 
+static uint32_t dac_channel2reg[] = {
+       [DA0] = DA0_reg,
+       [DA1] = DA1_reg,
+       [DA2] = DA2_reg,
+       [DA3] = DA3_reg,
+       [DA4] = DA4_reg,
+       [DA5] = DA5_reg,
+       [DA6] = DA6_reg,
+       [DA7] = DA7_reg,
+};
+
+static uint32_t adc_channel2reg[] = {
+       [AD0] = ADDATA0_reg,
+       [AD1] = ADDATA1_reg,
+       [AD2] = ADDATA2_reg,
+       [AD3] = ADDATA3_reg,
+       [AD4] = ADDATA4_reg,
+       [AD5] = ADDATA5_reg,
+       [AD6] = ADDATA6_reg,
+       [AD7] = ADDATA7_reg,
+};
+
+typedef struct mf624_state_t {
+       int device_fd;
+       char *uio_dev;
+       bar_mapping_t bar0;
+       bar_mapping_t bar2;
+       bar_mapping_t bar4;
+       int status;
+       int ADC_enabled; // Which ADCs are enabled
+} mf624_state_t;
 
-int status;
-void* mf624_BAR0 = NULL;
-void* mf624_BAR2 = NULL;
-void* mf624_BAR4 = NULL;
-int BAR0_phys_addr;
-int BAR2_phys_addr;
-int BAR4_phys_addr;
-int ADC_enabled; // Which ADCs are enabled 
+#define MFST2REG(mfst, bar_num, reg_offs) \
+       ((void *)(mfst->bar##bar_num.virt_addr + (reg_offs)))
 
+mf624_state_t mf624_state;
 
 /* Print one byte as binary number */
 void print_8bin(int nr)
@@ -97,142 +185,100 @@ void print_8bin(int nr)
        printf("\n");
 }
 
-static inline int16_t mf624_read16(uint16_t *ptr)
+static inline int16_t mf624_read16(void *ptr)
 {
-       return (volatile uint16_t) *ptr;
+       return *(volatile uint16_t*)ptr;
 }
-static inline int32_t mf624_read32(uint32_t *ptr)
+static inline int32_t mf624_read32(void *ptr)
 {
-       return (volatile uint32_t) *ptr;
+       return *(volatile uint32_t*) ptr;
 }
 
-static inline void mf624_write16(uint16_t val, uint16_t *ptr)
+static inline void mf624_write16(uint16_t val, void *ptr)
 {
        *(volatile uint16_t*) ptr = val;
 }
 
-static inline void mf624_write32(uint32_t val, uint32_t *ptr)
+static inline void mf624_write32(uint32_t val, void *ptr)
 {
        *(volatile uint32_t*) ptr = val;
 }
 
-void DIO_write(int16_t val)
+void DIO_write(mf624_state_t* mfst, int16_t val)
 {
-       mf624_write16(val, mf624_BAR2 + DOUT_reg); 
+       mf624_write16(val, MFST2REG(mfst, 2, DOUT_reg));
 }
 
-uint16_t DIO_read()
+uint16_t DIO_read(mf624_state_t* mfst)
 {
-       return mf624_read16(mf624_BAR2 + DIN_reg) & 0xFF; 
+       return mf624_read16(MFST2REG(mfst, 2, DIN_reg)) & 0xFF;
 }
 
-void DAC_enable()
+void DAC_enable(mf624_state_t* mfst)
 {
        // Setting DACEN and LDAC bits in GPIO register influences all DACs
-       mf624_write32((mf624_read32(mf624_BAR0 + GPIOC_reg) 
-               | GPIOC_DACEN_mask) // enable output 
+       mf624_write32((mf624_read32(MFST2REG(mfst, 0, GPIOC_reg))
+               | GPIOC_DACEN_mask) // enable output
                & ~GPIOC_LDAC_mask, // enable conversion
-               mf624_BAR0 + GPIOC_reg); 
+               MFST2REG(mfst, 0, GPIOC_reg));
 }
 
-void DAC_write(dac_channel_t channel, int val) {
-       switch (channel) {
-               case DA0:
-                       mf624_write16(val, mf624_BAR2 + DA0_reg); 
-                       break;
-               case DA1:
-                       mf624_write16(val, mf624_BAR2 + DA1_reg); 
-                       break;
-               case DA2:
-                       mf624_write16(val, mf624_BAR2 + DA2_reg); 
-                       break;
-               case DA3:
-                       mf624_write16(val, mf624_BAR2 + DA3_reg); 
-                       break;
-               case DA4:
-                       mf624_write16(val, mf624_BAR2 + DA4_reg); 
-                       break;
-               case DA5:
-                       mf624_write16(val, mf624_BAR2 + DA5_reg); 
-                       break;
-               case DA6:
-                       mf624_write16(val, mf624_BAR2 + DA6_reg); 
-                       break;
-               case DA7:
-                       mf624_write16(val, mf624_BAR2 + DA7_reg); 
-                       break;
-               default:
-                       printf("FFFUUU!\n");
-       }
+int DAC_write(mf624_state_t* mfst, dac_channel_t channel, int val)
+{
+       if (channel > sizeof(dac_channel2reg)/sizeof(*dac_channel2reg))
+               return -1;
+
+       mf624_write16(val, MFST2REG(mfst, 2, dac_channel2reg[channel]));
+       return 0;
 }
 
-void ADC_enable(adc_channel_t channel)
+int ADC_enable(mf624_state_t* mfst, adc_channel_t channel)
 {
-       ADC_enabled = 0;
-
-       switch (channel) {
-               case AD0:
-                       ADC_enabled = (1 << 0);
-                       break;
-               case AD1:
-                       ADC_enabled = (1 << 1);
-                       break;
-               case AD2:
-                       ADC_enabled = (1 << 2);
-                       break;
-               case AD3:
-                       ADC_enabled = (1 << 3);
-                       break;
-               case AD4:
-                       ADC_enabled = (1 << 4);
-                       break;
-               case AD5:
-                       ADC_enabled = (1 << 5);
-                       break;
-               case AD6:
-                       ADC_enabled = (1 << 6);
-                       break;
-               case AD7:
-                       ADC_enabled = (1 << 7);
-                       break;
-               default:
-                       printf("FFFUUU!\n");
-       }
-       
-       ADC_enabled &= 0xFF;
-       mf624_write16(ADC_enabled, mf624_BAR2 + ADCTRL_reg);
+       mfst->ADC_enabled = 0;
+
+       if (channel > sizeof(adc_channel2reg)/sizeof(*adc_channel2reg))
+               return -1;
+
+       mfst->ADC_enabled = (1 << channel);
+
+       mfst->ADC_enabled &= 0xFF;
+       mf624_write16(mfst->ADC_enabled, MFST2REG(mfst, 2, ADCTRL_reg));
        //print_8bin(ADC_enabled);
+
+       return 0;
 }
 
 /* This function blocks until conversion is finished */
-double ADC_read(adc_channel_t channel)
+double ADC_read(mf624_state_t* mfst, adc_channel_t channel)
 {
-       int i;
+       volatile int i;
        int result;
 
        // Activate trigger to start conversion
-       mf624_read16(mf624_BAR2 + ADSTART_reg); 
+       mf624_read16(MFST2REG(mfst, 2, ADSTART_reg));
 
        // Check if conversion has finished
-       while((mf624_read32(mf624_BAR0 + GPIOC_reg) & GPIOC_EOLC_mask)) {       
+       while((mf624_read32(MFST2REG(mfst, 0, GPIOC_reg)) & GPIOC_EOLC_mask)) { 
                for (i = 0; i < 1000; i++) {} // small wait
        }
 
-       ADC_enable(channel);
-       result = mf624_read16(mf624_BAR2 + ADDATA0_reg);
+       ADC_enable(mfst, channel);
+       result = mf624_read16(MFST2REG(mfst, 2, ADDATA0_reg));
 
        return 10.0 * ((int16_t) (result << 2)) / (double) 0x8000;
 }
 
 
 int open_device(char* path) {
-       status = open(path, O_RDWR);
-       if (status == -1) {
+       int device_fd;
+
+       device_fd = open(path, O_RDWR | O_SYNC);
+       if (device_fd == -1) {
                perror("open()");
                return -1;
        }
 
-       return status;
+       return device_fd;
 }
 
 void wait_for_interrupts(int device_fd)
@@ -243,6 +289,7 @@ void wait_for_interrupts(int device_fd)
 int disable_interrupts(int device_fd)
 {
        uint32_t control_value = 0;
+       int status;
 
        status = write(device_fd, &control_value, sizeof(uint32_t));
        if (status == -1) {
@@ -256,6 +303,7 @@ int disable_interrupts(int device_fd)
 int enable_interrupts(int device_fd)
 {
        uint32_t control_value = 1;
+       int status;
 
        status = write(device_fd, &control_value, sizeof(uint32_t));
        if (status == -1) {
@@ -268,6 +316,7 @@ int enable_interrupts(int device_fd)
 
 void list_available_mem_regions(char* device)
 {
+       int status;
        char path[] = "/sys/class/uio/";
        char subdir[] = "/maps/";
        char directory[BUFF_MID];
@@ -297,12 +346,13 @@ void list_available_mem_regions(char* device)
                perror("closedir()");
                return;
        }
-       
+
 }
 
 
 void list_available_io_ports(char *device)
 {
+       int status;
        char path[] = "/sys/class/uio/";
        char subdir[] = "/portio/";
        char directory[BUFF_MID];
@@ -344,6 +394,7 @@ void list_available_io_ports(char *device)
 
 void run_simple_tests(char* dev_name)
 {
+       int status;
        int device_fd;
        char buff[BUFF_SMALL];
        memset(buff, '\0', BUFF_SMALL);
@@ -360,7 +411,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) {
@@ -376,121 +427,117 @@ void run_simple_tests(char* dev_name)
        list_available_io_ports(dev_name);
 }
 
-void mmap_regions(int device_fd, char* uio_dev)
+int mmap_regions(mf624_state_t* mfst)
 {
-       char path[BUFF_MID];
-       FILE *file;
-
-       sprintf(path, "/sys/class/uio/%s/maps/map0/addr", uio_dev);
-       file = fopen(path, "rb");
-       fscanf(file, "%llx", &BAR0_phys_addr);
-       fclose(file);
-
-       sprintf(path, "/sys/class/uio/%s/maps/map1/addr", uio_dev);
-       file = fopen(path, "rb");
-       fscanf(file, "%llx", &BAR2_phys_addr);
-       fclose(file);
-
-       sprintf(path, "/sys/class/uio/%s/maps/map2/addr", uio_dev);
-       file = fopen(path, "rb");
-       fscanf(file, "%llx", &BAR4_phys_addr);
-       fclose(file);
-
+       if (bar_mapping_fill(&mfst->bar0, mfst->uio_dev, 0) < 0) {
+               fprintf(stderr, "%s bar0 mapping fill failed\n", mfst->uio_dev);
+               return -1;
+       }
 
-       mf624_BAR0 = mmap(0, 1 * sysconf(_SC_PAGESIZE), PROT_READ | PROT_WRITE, MAP_SHARED, device_fd, BAR0_offset);
-       if (mf624_BAR2 == MAP_FAILED) {
-               perror("mmap()");
+       if (bar_mapping_fill(&mfst->bar2, mfst->uio_dev, 1) < 0) {
+               fprintf(stderr, "%s bar2 mapping fill failed\n", mfst->uio_dev);
+               return -1;
        }
-       mf624_BAR0 += (BAR0_phys_addr & (sysconf(_SC_PAGESIZE) - 1));
 
+       if (bar_mapping_fill(&mfst->bar4, mfst->uio_dev, 2) < 0) {
+               fprintf(stderr, "%s bar4 mapping fill failed\n", mfst->uio_dev);
+               return -1;
+       }
 
-       mf624_BAR2 = mmap(0, 1 * sysconf(_SC_PAGESIZE), PROT_READ | PROT_WRITE, MAP_SHARED, device_fd, BAR2_offset);
-       if (mf624_BAR2 == MAP_FAILED) {
-               perror("mmap()");
+       if (bar_mapping_setup(&mfst->bar0, mfst->device_fd) < 0) {
+               fprintf(stderr, "%s bar0 mapping setup failed\n", mfst->uio_dev);
+               return -1;
        }
-       mf624_BAR2 += (BAR2_phys_addr & (sysconf(_SC_PAGESIZE) - 1));
 
+       if (bar_mapping_setup(&mfst->bar2, mfst->device_fd) < 0) {
+               fprintf(stderr, "%s bar2 mapping setup failed\n", mfst->uio_dev);
+               return -1;
+       }
 
-       mf624_BAR4 = mmap(0, 1 * sysconf(_SC_PAGESIZE), PROT_READ | PROT_WRITE, MAP_SHARED, device_fd, BAR4_offset);
-       if (mf624_BAR2 == MAP_FAILED) {
-               perror("mmap()");
+       if (bar_mapping_setup(&mfst->bar4, mfst->device_fd) < 0) {
+               fprintf(stderr, "%s bar4 mapping setup failed\n", mfst->uio_dev);
+               return -1;
        }
-       mf624_BAR4 += (BAR4_phys_addr & (sysconf(_SC_PAGESIZE) - 1));
 
-       /*
-       printf("BAR0_phys_addr = %x\n", BAR0_phys_addr);
-       printf("BAR2_phys_addr = %x\n", BAR2_phys_addr);
-       printf("BAR4_phys_addr = %x\n", BAR4_phys_addr);
+#if 1
+       printf("bar0.phys_addr = %"PRIxPTR"\n", mfst->bar0.phys_addr);
+       printf("bar2.phys_addr = %"PRIxPTR"\n", mfst->bar2.phys_addr);
+       printf("bar4.phys_addr = %"PRIxPTR"\n", mfst->bar4.phys_addr);
+
+       printf("bar0.virt_addr = %"PRIxPTR"\n", mfst->bar0.virt_addr);
+       printf("bar2.virt_addr = %"PRIxPTR"\n", mfst->bar2.virt_addr);
+       printf("bar4.virt_addr = %"PRIxPTR"\n", mfst->bar4.virt_addr);
+#endif
 
-       printf("mf624_BAR0 = %x\n", mf624_BAR0);
-       printf("mf624_BAR2 = %x\n", mf624_BAR2);
-       printf("mf624_BAR4 = %x\n", mf624_BAR4);
-       */
+       return 0;
 }
 
 
 int main(int argc, char* argv[])
 {
-       int device_fd;
+       mf624_state_t* mfst = &mf624_state;
        char buff[BUFF_SMALL];
        memset(buff, '\0', BUFF_SMALL);
 
        if (argc < 2) {
                printf("Usage: %s UIO_DEVICE\n   UIO_DEVICE\tname of uio device in /dev\n", argv[0]);
                return 1;
-       }       
+       }
+
+       mfst->uio_dev = argv[1];
 
        strncat(buff, "/dev/", 5);
-       strncat(buff, argv[1], min(strlen(argv[1]), 8));
+       strncat(buff, mfst->uio_dev, sizeof(buff) - 6);
 
-       device_fd = open_device(buff);
-       if (device_fd < 0) {
-               printf("%s does not exist!\n", argv[1]);
+       mfst->device_fd = open_device(buff);
+       if (mfst->device_fd < 0) {
+               fprintf(stderr, "%s open failed (%s)!\n", mfst->uio_dev, strerror(errno));
+               return 2;
+       }
+       if (mmap_regions(mfst) < 0) {
+               fprintf(stderr, "%s mmap_regions failed (%s)!\n", mfst->uio_dev, strerror(errno));
                return 2;
        }
-       mmap_regions(device_fd, argv[1]);
 
-       if (device_fd != -1) {
-               DAC_enable();
+       DAC_enable(mfst);
 
-               while (1){
-                       printf("Reading DIO: ");
-                       print_8bin(DIO_read());
-                       sleep(1);
+       while (1){
+               printf("Reading DIO: ");
+               print_8bin(DIO_read(mfst));
+               sleep(1);
 
-                       printf("Setting DA1 to 10 V\n");
-                       DAC_write(DA1, 0x3FFF);
-                       sleep(1);
+               printf("Setting DA1 to 10 V\n");
+               DAC_write(mfst, DA1, 0x3FFF);
+               sleep(1);
 
-                       printf("Reading ADC0: ");
-                       printf("%f V\n", ADC_read(AD0));
-                       sleep(1);
-       
-                       printf("Reading ADC1: ");
-                       printf("%f V\n", ADC_read(AD1));
-                       sleep(1);
-       
-                       printf("Setting DIO to 0xff\n");
-                       DIO_write(0xff);
-                       sleep(1);
-
-                       printf("Setting DIO to 0x00\n");
-                       DIO_write(0x00);
-                       sleep(1);
-
-                       printf("Setting DA1 to 5 V\n");
-                       DAC_write(DA1, 0x3000);
-                       sleep(1);
-                       
-                       printf("Reading ADC0: ");
-                       printf("%f V\n", ADC_read(AD0));
-                       sleep(1);
-       
-                       printf("Reading ADC1: ");
-                       printf("%f V\n", ADC_read(AD1));
-                       sleep(1);
-                       printf("----------------------\n\n");
-               }
+               printf("Reading ADC0: ");
+               printf("%f V\n", ADC_read(mfst, AD0));
+               sleep(1);
+
+               printf("Reading ADC1: ");
+               printf("%f V\n", ADC_read(mfst, AD1));
+               sleep(1);
+
+               printf("Setting DIO to 0xff\n");
+               DIO_write(mfst, 0xff);
+               sleep(1);
+
+               printf("Setting DIO to 0x00\n");
+               DIO_write(mfst, 0x00);
+               sleep(1);
+
+               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);
+
+               printf("Reading ADC1: ");
+               printf("%f V\n", ADC_read(mfst, AD1));
+               sleep(1);
+               printf("----------------------\n\n");
        }