]> rtime.felk.cvut.cz Git - mf6xx.git/blob - src/uio/mf624/userspace/test_application/main.c
0e94f1e773738021e3e3776bbe589e84fbb118ac
[mf6xx.git] / src / uio / mf624 / userspace / test_application / main.c
1 #include <stdio.h>
2 #include <errno.h>
3 #include <sys/stat.h>
4 #include <fcntl.h>
5 #include <unistd.h>
6 #include <string.h>
7 #include <dirent.h>
8 #include <sys/types.h>
9 #include <sys/mman.h>
10 #include <stdint.h> // uintX_t
11 #include <unistd.h>
12
13 #define BUFF_SMALL              32
14 #define BUFF_MID                256
15 #define min(a, b)               ((a) > (b) ? (b) : (a))
16
17 /* Hardware specific */
18 #define GPIOC_reg               0x54
19 #define DOUT_reg                0x10
20 #define DA0_reg                 0x20
21 #define DA1_reg                 0x22
22 #define DA2_reg                 0x24
23 #define DA3_reg                 0x26
24 #define DA4_reg                 0x28
25 #define DA5_reg                 0x2A
26 #define DA6_reg                 0x2C
27 #define DA7_reg                 0x2E
28
29 #define GPIOC_DACEN_mask        (1 << 26)
30 #define GPIOC_LDAC_mask         (1 << 23)       
31
32 #define BAR0_offset             (0 * sysconf(_SC_PAGESIZE))
33 #define BAR2_offset             (1 * sysconf(_SC_PAGESIZE))
34 #define BAR4_offset             (2 * sysconf(_SC_PAGESIZE))
35
36 typedef enum {DA0, DA1} dac_channel_t;
37
38 int status;
39 void* mf624_BAR0 = NULL;
40 void* mf624_BAR2 = NULL;
41 void* mf624_BAR4 = NULL;
42 int BAR0_phys_addr;
43 int BAR2_phys_addr;
44 int BAR4_phys_addr;
45
46 void print_8bin(int nr)
47 {
48         int i;
49         for (i = 7; i >= 0; i--) {
50                 printf("%d" , ((nr & (1 << i)) > 0));
51         }
52
53         printf("\n");
54 }
55
56 static inline int16_t mf624_read16(uint16_t *ptr)
57 {
58         return (volatile uint16_t) *ptr;
59 }
60 static inline int32_t mf624_read32(uint32_t *ptr)
61 {
62         return (volatile uint32_t) *ptr;
63 }
64
65 static inline void mf624_write16(uint16_t val, uint16_t *ptr)
66 {
67         *(volatile uint16_t*) ptr = val;
68 }
69
70 static inline void mf624_write32(uint32_t val, uint32_t *ptr)
71 {
72         *(volatile uint32_t*) ptr = val;
73 }
74
75 void DIO_write(int16_t val)
76 {
77         mf624_write16(val, mf624_BAR2 + DOUT_reg); 
78 }
79
80 uint16_t DIO_read()
81 {
82         return mf624_read16(mf624_BAR2 + DOUT_reg) & 0xF; 
83 }
84
85 void DAC_enable()
86 {
87         mf624_write16(mf624_read16(mf624_BAR2 + GPIOC_reg) 
88                 | GPIOC_DACEN_mask 
89                 & ~GPIOC_LDAC_mask, 
90                 mf624_BAR2 + GPIOC_reg); 
91 }
92
93 void DAC_write(dac_channel_t channel, int val) {
94         switch (channel) {
95                 case DA0:
96                         mf624_write16(val, mf624_BAR2 + DA0_reg); 
97                         break;
98                 case DA1:
99                         mf624_write16(val, mf624_BAR2 + DA1_reg); 
100                         break;
101                 default:
102                         printf("FFFUUU!\n");
103         }
104
105         
106
107 }
108
109 int open_device(char* path) {
110         status = open(path, O_RDWR);
111         if (status == -1) {
112                 perror("open()");
113                 return -1;
114         }
115
116         return status;
117 }
118
119 void wait_for_interrupts(int device_fd)
120 {
121         read(device_fd, NULL, 1);
122 }
123
124 int disable_interrupts(int device_fd)
125 {
126         uint32_t control_value = 0;
127
128         status = write(device_fd, &control_value, sizeof(uint32_t));
129         if (status == -1) {
130                 perror("write()");
131                 return -1;
132         }
133
134         return status;
135 }
136
137 int enable_interrupts(int device_fd)
138 {
139         uint32_t control_value = 1;
140
141         status = write(device_fd, &control_value, sizeof(uint32_t));
142         if (status == -1) {
143                 perror("write()");
144                 return -1;
145         }
146
147         return status;
148 }
149
150 void list_available_mem_regions(char* device)
151 {
152         char path[] = "/sys/class/uio/";
153         char subdir[] = "/maps/";
154         char directory[BUFF_MID];
155         memset(directory, '\0', BUFF_MID);
156
157         DIR *dip;
158         struct dirent *dit;
159
160         strncat(directory, path, strlen(path));
161         strncat(directory, device, min(strlen(device), 8));
162         strncat(directory, subdir, strlen(subdir));
163
164         dip = opendir(directory);
165         if (dip == NULL) {
166                 perror("opendir");
167                 return;
168         }
169
170         while ((dit = readdir(dip)) != NULL) {
171                 if (strcmp(dit->d_name, ".") && strcmp(dit->d_name, "..")) {
172                         printf(" %s\n", dit->d_name);
173                 }
174         }
175
176         status = closedir(dip);
177         if (status == -1) {
178                 perror("closedir()");
179                 return;
180         }
181         
182 }
183
184
185 void list_available_io_ports(char *device)
186 {
187         char path[] = "/sys/class/uio/";
188         char subdir[] = "/portio/";
189         char directory[BUFF_MID];
190         memset(directory, '\0', BUFF_MID);
191
192         DIR *dip;
193         struct dirent *dit;
194
195         strncat(directory, path, strlen(path));
196         strncat(directory, device, min(strlen(device), 8));
197         strncat(directory, subdir, strlen(subdir));
198
199         status = access(directory, F_OK);
200         if (status == -1) {
201                 printf(" There are no IO port available\n");
202                 return;
203         }
204
205         dip = opendir(directory);
206         if (dip == NULL) {
207                 perror("opendir");
208                 return;
209         }
210
211         while ((dit = readdir(dip)) != NULL) {
212                 if (strcmp(dit->d_name, ".") && strcmp(dit->d_name, "..")) {
213                         printf(" %s\n", dit->d_name);
214                 }
215         }
216
217         status = closedir(dip);
218         if (status == -1) {
219                 perror("closedir()");
220                 return;
221         }
222
223 }
224
225
226 void run_simple_tests(char* dev_name)
227 {
228         int device_fd;
229         char buff[BUFF_SMALL];
230         memset(buff, '\0', BUFF_SMALL);
231
232         strncat(buff, "/dev/", 5);
233         strncat(buff, dev_name, min(strlen(dev_name), 8));
234
235         printf("Opening %s\n", buff);
236
237         device_fd = open_device(buff);
238         if (device_fd != -1) {
239                 printf("Tring to enable interrupts\n");
240                 status = enable_interrupts(device_fd);
241                 if (status != -1) {
242                         printf(" Probably OK\n");
243                 }
244                 
245                 printf("Tring to disable interrupts\n");
246                 status = disable_interrupts(device_fd);
247                 if (status != -1) {
248                         printf(" Probably OK\n");
249                 }
250         }
251
252
253         printf("Checking for available memory regions exported by the UIO driver\n");
254         list_available_mem_regions(dev_name);
255
256         printf("Checking for available IO ports exported by the UIO driver\n");
257         list_available_io_ports(dev_name);
258 }
259
260 void mmap_regions(int device_fd, char* uio_dev)
261 {
262         char path[BUFF_MID];
263         FILE *file;
264
265         sprintf(path, "/sys/class/uio/%s/maps/map0/addr", uio_dev);
266         file = fopen(path, "rb");
267         fscanf(file, "%llx", &BAR0_phys_addr);
268         fclose(file);
269
270         sprintf(path, "/sys/class/uio/%s/maps/map1/addr", uio_dev);
271         file = fopen(path, "rb");
272         fscanf(file, "%llx", &BAR2_phys_addr);
273         fclose(file);
274
275         sprintf(path, "/sys/class/uio/%s/maps/map2/addr", uio_dev);
276         file = fopen(path, "rb");
277         fscanf(file, "%llx", &BAR4_phys_addr);
278         fclose(file);
279
280
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) {
285                 perror("mmap()");
286         }
287         mf624_BAR0 += (BAR0_phys_addr & (sysconf(_SC_PAGESIZE) - 1));
288
289
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) {
292                 perror("mmap()");
293         }
294         mf624_BAR2 += (BAR2_phys_addr & (sysconf(_SC_PAGESIZE) - 1));
295
296
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) {
299                 perror("mmap()");
300         }
301         mf624_BAR4 += (BAR4_phys_addr & (sysconf(_SC_PAGESIZE) - 1));
302
303         /*
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);
307
308         printf("mf624_BAR0 = %x\n", mf624_BAR0);
309         printf("mf624_BAR2 = %x\n", mf624_BAR2);
310         printf("mf624_BAR4 = %x\n", mf624_BAR4);
311         */
312 }
313
314
315 int main(int argc, char* argv[])
316 {
317         int device_fd;
318         char buff[BUFF_SMALL];
319         memset(buff, '\0', BUFF_SMALL);
320
321         if (argc < 2) {
322                 printf("Usage: %s UIO_DEVICE\n   UIO_DEVICE\tname of uio device in /dev\n", argv[0]);
323                 return 1;
324         }       
325
326         strncat(buff, "/dev/", 5);
327         strncat(buff, argv[1], min(strlen(argv[1]), 8));
328
329         device_fd = open_device(buff);
330         mmap_regions(device_fd, argv[1]);
331
332         if (device_fd != -1) {
333                 DAC_enable();
334
335
336                 while (1){
337                         printf("Reading DIO = ");
338                         print_8bin(DIO_read());
339                         sleep(1);
340         
341                         printf("Setting DA0 to 10 V\n");
342                         DAC_write(DA0, 0x3FFF);
343                         sleep(1);
344
345                         printf("Setting DIO to 0xff\n");
346                         DIO_write(0xff);
347                         sleep(1);
348
349                         printf("Setting DIO to 0x00\n");
350                         DIO_write(0x00);
351                         sleep(1);
352
353                         printf("Setting DA0 to 5 V\n");
354                         DAC_write(DA0, 0x3000);
355                         sleep(1);
356                         
357                         printf("----------------------\n\n");
358                 }
359         }
360
361
362         return 0;
363 }