Add initial support for external DRAM init on the Raptor Versa ECP5-85 board
[gram.git] / examples / headless / main.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <stdint.h>
4 #include <string.h>
5 #include <time.h>
6
7 #include <fcntl.h>
8 #include <errno.h>
9 #include <termios.h>
10 #include <unistd.h>
11
12 #include <netinet/in.h>
13
14 #include <gram.h>
15
16 uint32_t gram_read(struct gramCtx *ctx, void *addr) {
17 uint8_t commands[6] = { 0x02, 0x01 };
18 uint32_t reply;
19 int received, sent, fd;
20
21 fd = *(int*)(ctx->user_data);
22
23 *(uint32_t*)(&commands[2]) = htonl((uint32_t)addr >> 2);
24
25 sent = write(fd, commands, sizeof(commands));
26 if (sent != sizeof(commands)) {
27 fprintf(stderr, "gram_read error (sent bytes length mismatch)\n");
28 }
29 received = read(fd, &reply, sizeof(reply));
30 if (received != sizeof(reply)) {
31 fprintf(stderr, "gram_read error (read bytes length mismatch: %d != %d)\n", received, sizeof(reply));
32 }
33
34 //printf("gram_read: 0x%08x: 0x%08x\n", addr, ntohl(reply));
35
36 return ntohl(reply);
37 }
38
39 int gram_write(struct gramCtx *ctx, void *addr, uint32_t value) {
40 uint8_t commands[10] = { 0x01, 0x01 };
41 int sent;
42
43 *(uint32_t*)(commands+2) = htonl((uint32_t)addr >> 2);
44 *(uint32_t*)(commands+6) = htonl(value);
45
46 //printf("gram_write: 0x%08x: 0x%08x\n", addr, value);
47
48 sent = write(*(int*)(ctx->user_data), commands, sizeof(commands));
49 if (sent != sizeof(commands)) {
50 fprintf(stderr, "gram_write error (sent bytes length mismatch)\n");
51 return -1;
52 }
53
54 return 0;
55 }
56
57 int serial_setup(const char *devname, int baudrate) {
58 struct termios tty;
59 int serialfd;
60
61 serialfd = open("/dev/ttyUSB1", O_RDWR|O_NOCTTY);
62 if (serialfd < 0) {
63 fprintf(stderr, "Error %i from open: %s\n", errno, strerror(errno));
64 }
65
66 memset(&tty, 0, sizeof(tty));
67 if (tcgetattr(serialfd, &tty) != 0) {
68 fprintf(stderr, "Error %i from tcgetattr: %s\n", errno, strerror(errno));
69 }
70
71 /* Parameters from flterm */
72 tcgetattr(serialfd, &tty);
73 tty.c_cflag = B115200;
74 tty.c_cflag |= CS8;
75 tty.c_cflag |= CREAD;
76 tty.c_iflag = IGNPAR | IGNBRK;
77 tty.c_cflag |= CLOCAL;
78 tty.c_oflag = 0;
79 tty.c_lflag = 0;
80 tty.c_cc[VTIME] = 0;
81 tty.c_cc[VMIN] = 1;
82 tcsetattr(serialfd, TCSANOW, &tty);
83 tcflush(serialfd, TCOFLUSH);
84 tcflush(serialfd, TCIFLUSH);
85
86 cfsetispeed(&tty, B115200);
87 cfsetospeed(&tty, B115200);
88
89 cfmakeraw(&tty);
90
91 tcflush(serialfd, TCIFLUSH );
92 if (tcsetattr(serialfd, TCSANOW, &tty) != 0) {
93 fprintf(stderr, "Error %i from tcsetattr: %s\n", errno, strerror(errno));
94 }
95
96 return serialfd;
97 }
98
99 int main(int argc, char *argv[]) {
100 struct gramCtx ctx;
101 int serial_port, baudrate = 0;
102 uint32_t read_value, expected_value;
103 const size_t kPatternSize = 512;
104 uint32_t pattern[kPatternSize];
105 const int kDumpWidth = 8;
106 size_t i;
107 int res;
108 uint32_t tmp;
109 int delay, miss = 0;
110
111 uint32_t ddr_base = 0x10000000;
112
113 #if 1
114 struct gramProfile profile = {
115 .mode_registers = {
116 0x2708, 0x2054, 0x0512, 0x0000
117 },
118 .rdly_p0 = 2,
119 .rdly_p1 = 2,
120 };
121 #endif
122 #if 0
123 struct gramProfile profile = {
124 .mode_registers = {
125 0x320, 0x6, 0x200, 0x0
126 },
127 .rdly_p0 = 2,
128 .rdly_p1 = 2,
129 };
130 #endif
131 struct gramProfile profile2;
132
133 if (argc < 3) {
134 fprintf(stderr, "Usage: %s port baudrate\n", argv[0]);
135 return EXIT_FAILURE;
136 }
137
138 sscanf(argv[2], "%d", &baudrate);
139 if (baudrate <= 0) {
140 fprintf(stderr, "%d is not a valid baudrate\n", baudrate);
141 }
142
143 printf("Port: %s, baudrate: %d\n", argv[1], baudrate);
144
145 serial_port = serial_setup(argv[1], baudrate);
146 ctx.user_data = &serial_port;
147
148 printf("gram init... ");
149 gram_init(&ctx, &profile, (void*)ddr_base, (void*)0x00009000, (void*)0x00008000);
150 printf("done\n");
151
152 printf("Rdly\np0: ");
153 for (size_t i = 0; i < 8; i++) {
154 profile2.rdly_p0 = i;
155 gram_load_calibration(&ctx, &profile2);
156 gram_reset_burstdet(&ctx);
157 for (size_t j = 0; j < 128; j++) {
158 tmp = gram_read(&ctx, ddr_base+4*j);
159 }
160 if (gram_read_burstdet(&ctx, 0)) {
161 printf("1");
162 } else {
163 printf("0");
164 }
165 fflush(stdout);
166 }
167 printf("\n");
168
169 printf("Rdly\np1: ");
170 for (size_t i = 0; i < 8; i++) {
171 profile2.rdly_p1 = i;
172 gram_load_calibration(&ctx, &profile2);
173 gram_reset_burstdet(&ctx);
174 for (size_t j = 0; j < 128; j++) {
175 tmp = gram_read(&ctx, ddr_base+4*j);
176 }
177 if (gram_read_burstdet(&ctx, 1)) {
178 printf("1");
179 } else {
180 printf("0");
181 }
182 fflush(stdout);
183 }
184 printf("\n");
185
186 printf("Auto calibrating... ");
187 res = gram_generate_calibration(&ctx, &profile2);
188 if (res != GRAM_ERR_NONE) {
189 printf("failed\n");
190 gram_load_calibration(&ctx, &profile);
191 } else {
192 gram_load_calibration(&ctx, &profile2);
193 }
194 printf("done\n");
195
196 printf("Auto calibration profile:\n");
197 printf("\tp0 rdly: %d\n", profile2.rdly_p0);
198 printf("\tp1 rdly: %d\n", profile2.rdly_p1);
199
200 gram_reset_burstdet(&ctx);
201
202 srand(time(NULL));
203 for (i = 0; i < kPatternSize; i++) {
204 pattern[i] = rand();
205 }
206
207 printf("memtest... \n");
208
209 printf("Writing data sequence...");
210 for (i = 0; i < kPatternSize; i++) {
211 gram_write(&ctx, ddr_base+4*i, pattern[i]);
212 }
213 printf("done\n");
214
215 if (argc >= 4) {
216 sscanf(argv[3], "%d", &delay);
217 printf("waiting for %d second(s)...", delay);
218 fflush(stdout);
219 sleep(delay);
220 printf("done\n");
221 }
222
223 printf("Reading data sequence...\n");
224 for (i = 0; i < kPatternSize; i++) {
225 if ((i % kDumpWidth) == 0) {
226 printf("%08x | ", ddr_base+4*i);
227 }
228
229 read_value = gram_read(&ctx, ddr_base+4*i);
230 expected_value = pattern[i];
231
232 for (int j = 3; j >= 0; j--) {
233 if (((uint8_t*)(&read_value))[j] != ((uint8_t*)(&expected_value))[j]) {
234 printf("\033[0;31m%02x\033[0m", ((uint8_t*)(&read_value))[j]);
235 miss++;
236 } else {
237 printf("\033[0;32m%02x\033[0m", ((uint8_t*)(&read_value))[j]);
238 }
239 }
240
241 if ((i % kDumpWidth) == kDumpWidth-1) {
242 printf("\n");
243 } else {
244 printf(" ");
245 }
246 }
247
248 printf("Burstdet %d-%d\n", gram_read_burstdet(&ctx, 0), gram_read_burstdet(&ctx, 1));
249
250 printf("Memtest miss score (lowest is better): %d/100\n", (miss/4)*100/kPatternSize);
251
252 close(serial_port);
253
254 return EXIT_SUCCESS;
255 }