From: Pavel Pisa Date: Fri, 24 May 2013 13:12:42 +0000 (+0200) Subject: Cleanup of MF624 UIO code to work with recent Linux kernels. X-Git-Url: http://rtime.felk.cvut.cz/gitweb/mf6xx.git/commitdiff_plain/e57abff00beba6d71529322e3b74d539750f4aa9 Cleanup of MF624 UIO code to work with recent Linux kernels. Tested on 3.2.41 kernel on AMD64 Debian. Signed-off-by: Pavel Pisa --- diff --git a/src/uio/mf624/userspace/test_application/main.c b/src/uio/mf624/userspace/test_application/main.c old mode 100755 new mode 100644 index 401fa30..321a22e --- a/src/uio/mf624/userspace/test_application/main.c +++ b/src/uio/mf624/userspace/test_application/main.c @@ -28,7 +28,75 @@ #include #include #include // uintX_t +#include #include +#include + +/****************************************************************/ + +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 @@ -61,30 +129,50 @@ #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"); }