/alps/ipecamera

To get this branch, use:
bzr branch http://darksoft.org/webbzr/alps/ipecamera

« back to all changes in this revision

Viewing changes to apps/xilinx.c

  • Committer: Suren A. Chilingaryan
  • Date: 2015-04-27 00:28:57 UTC
  • Revision ID: csa@suren.me-20150427002857-82fk6r3e8rfgy4wr
First stand-alone ipecamera implementation

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#define _BSD_SOURCE
2
 
#define _POSIX_C_SOURCE 199309L
3
 
#include <stdio.h>
4
 
#include <stdlib.h>
5
 
#include <string.h>
6
 
#include <unistd.h>
7
 
#include <stdarg.h>
8
 
#include <time.h>
9
 
#include <sched.h>
10
 
#include <sys/time.h>
11
 
 
12
 
#include "pcilib.h"
13
 
#include "irq.h"
14
 
#include "kmem.h"
15
 
 
16
 
#define DEVICE "/dev/fpga0"
17
 
#define BAR PCILIB_BAR0
18
 
#define USE PCILIB_KMEM_USE(PCILIB_KMEM_USE_USER, 1)
19
 
#define STATIC_REGION 0x80000000 //  to reserve 512 MB at the specified address, add "memmap=512M$2G" to kernel parameters
20
 
#define BUFFERS 1
21
 
#define ITERATIONS 100
22
 
#define TLP_SIZE 64
23
 
#define HUGE_PAGE 4096  // number of pages per huge page
24
 
#define PAGE_SIZE 4096  // other values are not supported in the kernel
25
 
#define TIMEOUT 100000
26
 
 
27
 
/* IRQs are slow for some reason. REALTIME mode is slower. Adding delays does not really help,
28
 
otherall we have only 3 checks in average. Check ready seems to be not needed and adds quite 
29
 
much extra time */
30
 
#define USE_IRQ
31
 
//#define CHECK_READY
32
 
//#define REALTIME
33
 
//#define ADD_DELAYS
34
 
#define CHECK_RESULT
35
 
 
36
 
//#define WR(addr, value) { val = value; pcilib_write(pci, BAR, addr, sizeof(val), &val); }
37
 
//#define RD(addr, value) { pcilib_read(pci, BAR, addr, sizeof(val), &val); value = val; }
38
 
#define WR(addr, value) { *(uint32_t*)(bar + addr + offset) = value; }
39
 
#define RD(addr, value) { value = *(uint32_t*)(bar + addr + offset); }
40
 
 
41
 
static void fail(const char *msg, ...) {
42
 
    va_list va;
43
 
    
44
 
    va_start(va, msg);
45
 
    vprintf(msg, va);
46
 
    va_end(va);
47
 
    printf("\n");
48
 
 
49
 
    exit(-1);
50
 
}
51
 
 
52
 
void hpsleep(size_t ns) {
53
 
    struct timespec wait, tv;
54
 
 
55
 
    clock_gettime(CLOCK_REALTIME, &wait);
56
 
 
57
 
    wait.tv_nsec += ns;
58
 
    if (wait.tv_nsec > 999999999) {
59
 
        wait.tv_sec += 1;
60
 
        wait.tv_nsec = 1000000000 - wait.tv_nsec;
61
 
    }
62
 
 
63
 
    do {
64
 
        clock_gettime(CLOCK_REALTIME, &tv);
65
 
    } while ((wait.tv_sec > tv.tv_sec)||((wait.tv_sec == tv.tv_sec)&&(wait.tv_nsec > tv.tv_nsec)));
66
 
}
67
 
 
68
 
 
69
 
int main() {
70
 
    int err;
71
 
    long i, j;
72
 
    pcilib_t *pci;
73
 
    pcilib_kmem_handle_t *kbuf;
74
 
    uint32_t status;
75
 
    struct timeval start, end;
76
 
    size_t size, run_time;
77
 
    void* volatile bar;
78
 
    uintptr_t bus_addr[BUFFERS];
79
 
 
80
 
    pcilib_bar_t bar_tmp = BAR; 
81
 
    uintptr_t offset = 0;
82
 
 
83
 
    pcilib_kmem_flags_t clean_flags = PCILIB_KMEM_FLAG_HARDWARE|PCILIB_KMEM_FLAG_PERSISTENT|PCILIB_KMEM_FLAG_EXCLUSIVE;
84
 
 
85
 
#ifdef ADD_DELAYS
86
 
    long rpt = 0, rpt2 = 0;
87
 
    size_t best_time;
88
 
    best_time = 1000000000L * HUGE_PAGE * PAGE_SIZE / (4L * 1024 * 1024 * 1024);
89
 
#endif /* ADD_DELAYS */
90
 
 
91
 
#ifdef REALTIME
92
 
    pid_t pid;
93
 
    struct sched_param sched = {0};
94
 
 
95
 
    pid = getpid();
96
 
    sched.sched_priority = sched_get_priority_min(SCHED_FIFO);
97
 
    if (sched_setscheduler(pid, SCHED_FIFO, &sched))
98
 
        printf("Warning: not able to get real-time priority\n");
99
 
#endif /* REALTIME */
100
 
 
101
 
    pci = pcilib_open(DEVICE, PCILIB_MODEL_DETECT);
102
 
    if (!pci) fail("pcilib_open");
103
 
 
104
 
    bar = pcilib_map_bar(pci, BAR);
105
 
    if (!bar) {
106
 
        pcilib_close(pci);
107
 
        fail("map bar");
108
 
    }
109
 
 
110
 
    pcilib_detect_address(pci, &bar_tmp, &offset, 1);
111
 
 
112
 
        // Reset
113
 
    WR(0x00, 1)
114
 
    usleep(1000);
115
 
    WR(0x00, 0)
116
 
 
117
 
    pcilib_enable_irq(pci, PCILIB_IRQ_TYPE_ALL, 0);
118
 
    pcilib_clear_irq(pci, PCILIB_IRQ_SOURCE_DEFAULT);
119
 
 
120
 
    pcilib_clean_kernel_memory(pci, USE, clean_flags);
121
 
 
122
 
#ifdef STATIC_REGION
123
 
    kbuf = pcilib_alloc_kernel_memory(pci, PCILIB_KMEM_TYPE_REGION_C2S, BUFFERS, HUGE_PAGE * PAGE_SIZE, STATIC_REGION, USE, 0);
124
 
#else /* STATIC_REGION */
125
 
    kbuf = pcilib_alloc_kernel_memory(pci, PCILIB_KMEM_TYPE_DMA_C2S_PAGE, BUFFERS, HUGE_PAGE * PAGE_SIZE, 4096, USE, 0);
126
 
#endif /* STATIC_REGION */
127
 
 
128
 
    if (!kbuf) {
129
 
        printf("KMem allocation failed\n");
130
 
        exit(0);
131
 
    }
132
 
 
133
 
 
134
 
#ifdef CHECK_RESULT    
135
 
    volatile uint32_t *ptr0 = pcilib_kmem_get_block_ua(pci, kbuf, 0);
136
 
 
137
 
    memset((void*)ptr0, 0, (HUGE_PAGE * PAGE_SIZE));
138
 
    
139
 
    for (i = 0; i < (HUGE_PAGE * PAGE_SIZE / 4); i++) {
140
 
        if (ptr0[i] != 0) break;
141
 
    }
142
 
    if (i < (HUGE_PAGE * PAGE_SIZE / 4)) {
143
 
        printf("Initialization error in position %lu, value = %x\n", i * 4, ptr0[i]);
144
 
    }
145
 
#endif /* CHECK_RESULT */
146
 
 
147
 
    WR(0x04, 0)
148
 
    WR(0x0C, TLP_SIZE)
149
 
    WR(0x10, (HUGE_PAGE * (PAGE_SIZE / (4 * TLP_SIZE))))
150
 
    WR(0x14, 0x13131313)
151
 
 
152
 
    for (j = 0; j < BUFFERS; j++ ) {
153
 
        bus_addr[j] = pcilib_kmem_get_block_ba(pci, kbuf, j);
154
 
    }
155
 
 
156
 
    gettimeofday(&start, NULL);
157
 
 
158
 
    for (i = 0; i < ITERATIONS; i++) {
159
 
        for (j = 0; j < BUFFERS; j++ ) {
160
 
//          uintptr_t ba = pcilib_kmem_get_block_ba(pci, kbuf, j);
161
 
//          WR(0x08, ba)
162
 
            WR(0x08, bus_addr[j]);
163
 
            WR(0x04, 0x01)
164
 
 
165
 
#ifdef USE_IRQ
166
 
            err = pcilib_wait_irq(pci, PCILIB_IRQ_SOURCE_DEFAULT, TIMEOUT, NULL);
167
 
            if (err) printf("Timeout waiting for IRQ, err: %i\n", err);
168
 
 
169
 
            RD(0x04, status);
170
 
            if ((status&0xFFFF) != 0x101) printf("Invalid status %x\n", status);
171
 
//          WR(0x04, 0x00);
172
 
#else /* USE_IRQ */
173
 
# ifdef ADD_DELAYS
174
 
//          hpsleep(best_time);
175
 
            do {
176
 
                rpt++;
177
 
                RD(0x04, status);
178
 
            } while (status != 0x101);
179
 
# else /* ADD_DELAYS */
180
 
            do {
181
 
                RD(0x04, status);
182
 
            } while (status != 0x101);
183
 
# endif /* ADD_DELAYS */
184
 
#endif /* USE_IRQ */
185
 
 
186
 
            WR(0x00, 1)
187
 
#ifdef CHECK_READY
188
 
            do {
189
 
                rpt2++;
190
 
                RD(0x04, status);
191
 
            } while (status != 0);
192
 
#endif /* CHECK_READY */
193
 
            WR(0x00, 0)
194
 
        }
195
 
    }
196
 
    gettimeofday(&end, NULL);
197
 
 
198
 
#ifdef CHECK_RESULT    
199
 
    pcilib_kmem_sync_block(pci, kbuf, PCILIB_KMEM_SYNC_FROMDEVICE, 0);
200
 
 
201
 
    for (i = 0; i < (HUGE_PAGE * PAGE_SIZE / 4); i++) {
202
 
//      printf("%lx ", ptr0[i]);
203
 
        if (ptr0[i] != 0x13131313) break;
204
 
    }
205
 
    if (i < (HUGE_PAGE * PAGE_SIZE / 4)) {
206
 
        printf("Error in position %lu, value = %x\n", i * 4, ptr0[i]);
207
 
    }
208
 
#endif /* CHECK_RESULT */
209
 
 
210
 
    pcilib_free_kernel_memory(pci, kbuf,  0);
211
 
    pcilib_disable_irq(pci, 0);
212
 
    pcilib_unmap_bar(pci, BAR, bar);
213
 
    pcilib_close(pci);
214
 
 
215
 
    run_time = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec);
216
 
    size = (long long int)ITERATIONS * BUFFERS * HUGE_PAGE * PAGE_SIZE;
217
 
 
218
 
    printf("%.3lf GB/s: transfered %zu bytes in %zu us using %u buffers\n", 1000000. * size / run_time / 1024 / 1024 / 1024, size, run_time, BUFFERS);
219
 
 
220
 
# ifdef ADD_DELAYS
221
 
    printf("Repeats: %lf, %lf\n",1. * rpt / (ITERATIONS * BUFFERS), 1. * rpt2 / (ITERATIONS * BUFFERS));
222
 
#endif /* USE_IRQ */        
223
 
 
224
 
 
225
 
}