10 #include <stdint.h> // uintX_t
15 #define min(a, b) ((a) > (b) ? (b) : (a))
17 /* Hardware specific */
18 #define GPIOC_reg 0x54
29 #define GPIOC_DACEN_mask (1 << 26)
30 #define GPIOC_LDAC_mask (1 << 23)
32 #define BAR0_offset (0 * sysconf(_SC_PAGESIZE))
33 #define BAR2_offset (1 * sysconf(_SC_PAGESIZE))
34 #define BAR4_offset (2 * sysconf(_SC_PAGESIZE))
36 typedef enum {DA0, DA1} dac_channel_t;
39 void* mf624_BAR0 = NULL;
40 void* mf624_BAR2 = NULL;
41 void* mf624_BAR4 = NULL;
46 void print_8bin(int nr)
49 for (i = 7; i >= 0; i--) {
50 printf("%d" , ((nr & (1 << i)) > 0));
56 static inline int16_t mf624_read16(uint16_t *ptr)
58 return (volatile uint16_t) *ptr;
60 static inline int32_t mf624_read32(uint32_t *ptr)
62 return (volatile uint32_t) *ptr;
65 static inline void mf624_write16(uint16_t val, uint16_t *ptr)
67 *(volatile uint16_t*) ptr = val;
70 static inline void mf624_write32(uint32_t val, uint32_t *ptr)
72 *(volatile uint32_t*) ptr = val;
75 void DIO_write(int16_t val)
77 mf624_write16(val, mf624_BAR2 + DOUT_reg);
82 return mf624_read16(mf624_BAR2 + DOUT_reg) & 0xF;
87 mf624_write16(mf624_read16(mf624_BAR2 + GPIOC_reg)
90 mf624_BAR2 + GPIOC_reg);
93 void DAC_write(dac_channel_t channel, int val) {
96 mf624_write16(val, mf624_BAR2 + DA0_reg);
99 mf624_write16(val, mf624_BAR2 + DA1_reg);
109 int open_device(char* path) {
110 status = open(path, O_RDWR);
119 void wait_for_interrupts(int device_fd)
121 read(device_fd, NULL, 1);
124 int disable_interrupts(int device_fd)
126 uint32_t control_value = 0;
128 status = write(device_fd, &control_value, sizeof(uint32_t));
137 int enable_interrupts(int device_fd)
139 uint32_t control_value = 1;
141 status = write(device_fd, &control_value, sizeof(uint32_t));
150 void list_available_mem_regions(char* device)
152 char path[] = "/sys/class/uio/";
153 char subdir[] = "/maps/";
154 char directory[BUFF_MID];
155 memset(directory, '\0', BUFF_MID);
160 strncat(directory, path, strlen(path));
161 strncat(directory, device, min(strlen(device), 8));
162 strncat(directory, subdir, strlen(subdir));
164 dip = opendir(directory);
170 while ((dit = readdir(dip)) != NULL) {
171 if (strcmp(dit->d_name, ".") && strcmp(dit->d_name, "..")) {
172 printf(" %s\n", dit->d_name);
176 status = closedir(dip);
178 perror("closedir()");
185 void list_available_io_ports(char *device)
187 char path[] = "/sys/class/uio/";
188 char subdir[] = "/portio/";
189 char directory[BUFF_MID];
190 memset(directory, '\0', BUFF_MID);
195 strncat(directory, path, strlen(path));
196 strncat(directory, device, min(strlen(device), 8));
197 strncat(directory, subdir, strlen(subdir));
199 status = access(directory, F_OK);
201 printf(" There are no IO port available\n");
205 dip = opendir(directory);
211 while ((dit = readdir(dip)) != NULL) {
212 if (strcmp(dit->d_name, ".") && strcmp(dit->d_name, "..")) {
213 printf(" %s\n", dit->d_name);
217 status = closedir(dip);
219 perror("closedir()");
226 void run_simple_tests(char* dev_name)
229 char buff[BUFF_SMALL];
230 memset(buff, '\0', BUFF_SMALL);
232 strncat(buff, "/dev/", 5);
233 strncat(buff, dev_name, min(strlen(dev_name), 8));
235 printf("Opening %s\n", buff);
237 device_fd = open_device(buff);
238 if (device_fd != -1) {
239 printf("Tring to enable interrupts\n");
240 status = enable_interrupts(device_fd);
242 printf(" Probably OK\n");
245 printf("Tring to disable interrupts\n");
246 status = disable_interrupts(device_fd);
248 printf(" Probably OK\n");
253 printf("Checking for available memory regions exported by the UIO driver\n");
254 list_available_mem_regions(dev_name);
256 printf("Checking for available IO ports exported by the UIO driver\n");
257 list_available_io_ports(dev_name);
260 void mmap_regions(int device_fd, char* uio_dev)
265 sprintf(path, "/sys/class/uio/%s/maps/map0/addr", uio_dev);
266 file = fopen(path, "rb");
267 fscanf(file, "%llx", &BAR0_phys_addr);
270 sprintf(path, "/sys/class/uio/%s/maps/map1/addr", uio_dev);
271 file = fopen(path, "rb");
272 fscanf(file, "%llx", &BAR2_phys_addr);
275 sprintf(path, "/sys/class/uio/%s/maps/map2/addr", uio_dev);
276 file = fopen(path, "rb");
277 fscanf(file, "%llx", &BAR4_phys_addr);
281 //FIXME size of memory must be in multiples of memory pages
282 // size = (size + PAGE_SIZE -1) / PAGE_SIZE * PAGE_SIZE; ?
283 mf624_BAR0 = mmap(0, 1 * sysconf(_SC_PAGESIZE), PROT_READ | PROT_WRITE, MAP_SHARED, device_fd, BAR0_offset);
284 if (mf624_BAR2 == MAP_FAILED) {
287 mf624_BAR0 += (BAR0_phys_addr & (sysconf(_SC_PAGESIZE) - 1));
290 mf624_BAR2 = mmap(0, 1 * sysconf(_SC_PAGESIZE), PROT_READ | PROT_WRITE, MAP_SHARED, device_fd, BAR2_offset);
291 if (mf624_BAR2 == MAP_FAILED) {
294 mf624_BAR2 += (BAR2_phys_addr & (sysconf(_SC_PAGESIZE) - 1));
297 mf624_BAR4 = mmap(0, 1 * sysconf(_SC_PAGESIZE), PROT_READ | PROT_WRITE, MAP_SHARED, device_fd, BAR4_offset);
298 if (mf624_BAR2 == MAP_FAILED) {
301 mf624_BAR4 += (BAR4_phys_addr & (sysconf(_SC_PAGESIZE) - 1));
304 printf("BAR0_phys_addr = %x\n", BAR0_phys_addr);
305 printf("BAR2_phys_addr = %x\n", BAR2_phys_addr);
306 printf("BAR4_phys_addr = %x\n", BAR4_phys_addr);
308 printf("mf624_BAR0 = %x\n", mf624_BAR0);
309 printf("mf624_BAR2 = %x\n", mf624_BAR2);
310 printf("mf624_BAR4 = %x\n", mf624_BAR4);
315 int main(int argc, char* argv[])
318 char buff[BUFF_SMALL];
319 memset(buff, '\0', BUFF_SMALL);
322 printf("Usage: %s UIO_DEVICE\n UIO_DEVICE\tname of uio device in /dev\n", argv[0]);
326 strncat(buff, "/dev/", 5);
327 strncat(buff, argv[1], min(strlen(argv[1]), 8));
329 device_fd = open_device(buff);
330 mmap_regions(device_fd, argv[1]);
332 if (device_fd != -1) {
337 printf("Reading DIO = ");
338 print_8bin(DIO_read());
341 printf("Setting DA0 to 10 V\n");
342 DAC_write(DA0, 0x3FFF);
345 printf("Setting DIO to 0xff\n");
349 printf("Setting DIO to 0x00\n");
353 printf("Setting DA0 to 5 V\n");
354 DAC_write(DA0, 0x3000);
357 printf("----------------------\n\n");