Project

General

Profile

RE: Changes on MityDSP-L138 L138-DM-336-RI-J ยป fpga_loader.cpp

Kim Nielsen, 04/26/2023 12:40 PM

 
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <unistd.h>
4
#include <fcntl.h>
5
#include <sys/mman.h>
6
#include <errno.h>
7
#include <string.h>
8

    
9
#include "osal/osal.h"
10
#include "osal/regs_sysconfig.h"
11

    
12

    
13
#define FPGA_BASE_ADDR          (0x66000000) /* ARM side interface, CS5 */
14
#define GPIO_REG_BASE           (0x01E26000)
15

    
16

    
17
typedef struct GpioBankPair
18
{
19
	volatile uint32_t DIR;
20
	volatile uint32_t OUT_DATA;
21
	volatile uint32_t SET_DATA;
22
	volatile uint32_t CLR_DATA;
23
	volatile uint32_t IN_DATA;
24
	volatile uint32_t SET_RIS_TRIG;
25
	volatile uint32_t CLR_RIS_TRIG;
26
	volatile uint32_t SET_FAL_TRIG;
27
	volatile uint32_t CLR_FAL_TRIG;
28
	volatile uint32_t INTSTAT;
29
} tsGpioBankPair;
30

    
31
typedef struct GpioRegs
32
{
33
	volatile uint32_t REVID;
34
	volatile uint32_t reserved1;
35
	volatile uint32_t BINTEN;
36
	volatile uint32_t reserved2;
37
	tsGpioBankPair    BANKPAIR[4];
38
} tsGpioRegs;
39

    
40
static tsGpioRegs *mpGpioRegs;
41
static const unsigned int gnNUMBANKS = 8;
42
static const unsigned int gnIOPERBANK = 16;
43

    
44
// GPIO Access Functions
45
static void GPIO_SetPinValue(unsigned int Bank, unsigned int Offset)
46
{
47
  int bankpair = Bank >> 1;
48
  int shift = (Bank&1)*16+Offset;
49

    
50
  mpGpioRegs->BANKPAIR[bankpair].SET_DATA = 1<<shift;
51
}
52

    
53

    
54
static void GPIO_ClearPinValue(unsigned int Bank, unsigned int Offset)
55
{
56
  int bankpair = Bank >> 1;
57
  int shift = (Bank&1)*16+Offset;
58

    
59
  mpGpioRegs->BANKPAIR[bankpair].CLR_DATA = 1<<shift;
60
}
61

    
62
static int GPIO_GetPinValue(unsigned int Bank, unsigned int Offset)
63
{
64
  int bankpair = Bank>>1;
65
  int shift = (Bank&1)*16+Offset;
66
  return (mpGpioRegs->BANKPAIR[bankpair].IN_DATA & (1<<shift)) ? 1 : 0;
67
}
68

    
69
static void GPIO_SetPinDirection(unsigned int Bank, unsigned int Offset, int IsOutput, unsigned int Value)
70
{
71
  int bankpair = Bank >> 1;
72
  int shift = (Bank&1)*16+Offset;
73

    
74
//  ASSERT(Bank < 8);
75
//  ASSERT(Offset < 16);
76

    
77
  if (IsOutput)
78
  {
79
    if (Value)
80
      GPIO_SetPinValue(Bank,Offset);
81
    else
82
      GPIO_ClearPinValue(Bank,Offset);
83
    mpGpioRegs->BANKPAIR[bankpair].DIR &= ~(1<<shift);
84
  }
85
  else
86
  {
87
    mpGpioRegs->BANKPAIR[bankpair].DIR |= (1<<shift);
88
  }
89
}
90

    
91

    
92
static void FPGA_ResetEnable(void)
93
{
94
  GPIO_ClearPinValue(6, 15);
95
}
96

    
97
static void FPGA_ResetDisable(void)
98
{
99
  GPIO_SetPinValue(6, 15);
100
}
101

    
102
static void FPGA_WriteEnable(void)
103
{
104
  GPIO_ClearPinValue(3, 9);
105
}
106

    
107
static void FPGA_WriteDisable(void)
108
{
109
  GPIO_SetPinValue(3, 9);
110
}
111

    
112
static int FPGA_InitResponse(void)
113
{
114
  return (GPIO_GetPinValue(3, 9));
115
}
116

    
117
static void GPIO_Init(void)
118
{
119
  // Setup GPIO pin directions
120
  GPIO_SetPinDirection(6, 15, True,  1); // output: PROGRAM_B (/resetout GP6[15])
121
  GPIO_SetPinDirection(3,  9, True,  1); // output: RDWR_B    (/EMA_RW   GP3[9] )
122
  GPIO_SetPinDirection(1, 15, False, 0); // input:  INIT_B    (init      GP1[15])
123
}
124

    
125

    
126

    
127
// FPGA Load Routine
128
// returns 0 on success
129
int32_t loadFpga (const char_t *filename, bool reset_only=false, const char_t * board="")
130
{
131
  FILE *file;
132
  uint8_t *filedata;
133
  long filesize, i;
134
  uint8_t *fpgamem;
135
  bool_t boBitSwap;
136
  sysconfig_regs_t *mpSysRegs;
137
  uint32_t w32;
138

    
139
  // Open memory device (O_SYNC option disables cache)
140
  int fd;
141
  fd = open("/dev/mem", O_RDWR | O_SYNC);
142
  if (fd < 0)
143
  {
144
    printf("Failed to open /dev/mem\n");
145
    return -1;
146
  }
147

    
148
  // Get access to GPIO memory area (MMU) - getpagesize()
149
  mpGpioRegs = (tsGpioRegs *) mmap(0, sizeof(tsGpioRegs), PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_REG_BASE);
150
  if (mpGpioRegs == NULL)
151
  {
152
    printf("mmap Failed for mpGpioRegs\n");
153
    close(fd);
154
    return -1;
155
  }
156

    
157
  // Get access to FPGA memory address space for programming
158
  fpgamem = (uint8_t *) mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, fd, FPGA_BASE_ADDR);
159
  if (fpgamem == NULL)
160
  {
161
    printf("mmap Failed for fpgamem\n");
162
    munmap(mpGpioRegs, sizeof(tsGpioRegs));
163
    close(fd);
164
    return -1;
165
  }
166

    
167

    
168
  // Get access to the syscfg registers
169
//  mpSysRegs = (sysconfig_regs_t *) mmap(0, sizeof(sysconfig_regs_t), PROT_READ|PROT_WRITE, MAP_SHARED, fd, SYSCFG0_REG_BASE);
170
  // Only read access (write access to the sys cfg registers is only possible from kernel space - by chip design)
171
  mpSysRegs = (sysconfig_regs_t *) mmap(0, sizeof(sysconfig_regs_t), PROT_READ, MAP_SHARED, fd, SYSCFG0_REG_BASE);
172
  if (mpSysRegs == NULL)
173
  {
174
    munmap(mpGpioRegs, sizeof(tsGpioRegs));
175
    munmap(fpgamem, getpagesize());
176
    printf("mmap Failed for mpSysRegs\n");
177
    close(fd);
178
    return -1;
179
  }
180

    
181
  // Check pin mux configuration for EMA_A_Rw must be GPIO to enable fpga load
182
  w32 = mpSysRegs->PINMUX[7] & 0x0F000000;
183
  if (w32 != 0x08000000)
184
  {
185
    munmap(mpGpioRegs, sizeof(tsGpioRegs));
186
    munmap(fpgamem, getpagesize());
187
    munmap(mpSysRegs, sizeof(sysconfig_regs_t));
188
    printf("Pin EMA_A_Rw not configured as GPIO, fpga will not be loaded\n");
189
    printf("pinmux7: %08X\n", w32);
190
    close(fd);
191
    return -1;
192
  }
193

    
194
#if 0
195
  printf("PINMUX[7] = 0x%08X\n", w32);
196
  w32 &= 0xF0FFFFFF;  // Set EMA_A_Rw pin to work as GPIO required for fpga loading (else used as GPIO in fpga loader on ARM!)
197
  w32 |= 0x08000000;
198
  mpSysRegs->PINMUX[7] = w32;
199
  printf("PINMUX[7] = 0x%08X\n", w32);
200
  printf("PINMUX[7] = 0x%08X\n", mpSysRegs->PINMUX[7]);
201
#endif
202

    
203
  // Unmap access to SYS CONFIG registers
204
  munmap(mpSysRegs, sizeof(sysconfig_regs_t));
205

    
206
  // Done using the filedescriptor
207
  close(fd);
208

    
209
  if (reset_only)
210
  {
211
    GPIO_Init();
212
    FPGA_ResetEnable();
213
    munmap(fpgamem, getpagesize());
214
    munmap(mpGpioRegs, sizeof(tsGpioRegs));
215
    return 0;
216
  }
217

    
218
  // Open fpga file
219
  file = fopen(filename, "r");
220
  if (file == NULL)
221
  {
222
    printf("Failed to open fpga file\n");
223
    munmap(mpGpioRegs, sizeof(tsGpioRegs));
224
    munmap(fpgamem, getpagesize());
225
    return (errno);
226
  }
227

    
228
  //Extract header
229
  long offset = 0;
230
  if(strlen(board) != 0)
231
  {
232
    char header_buf[50]; // max header size is 50 char
233
    int header_size = 0;
234
    while(header_size <= 50)
235
    {
236
      header_buf[header_size] = fgetc(file);
237
      if(header_buf[header_size] == ':')
238
      {
239
        header_size ++;
240
        break;
241
      }
242
      header_size ++;
243
    }
244
    header_buf[header_size]='\0';
245
    offset =  (long)header_size;
246
    printf("header: '%s'\n",header_buf);
247

    
248
    // Extract version from header
249
    char * version = strtok(header_buf,"v=");
250
    // Remove end marker ':' from version string
251
    version[strlen(version)-1] = '\0';
252

    
253
    printf("FPGA version: %s\n",version);
254

    
255
    // Compare board version and FPGA version
256
    if(strcmp(board,version) != 0)
257
    {
258
      printf("Error: FPGA version doesn't match Board \"%s\" != \"%s\"\n",version, board);
259
      munmap(mpGpioRegs, sizeof(tsGpioRegs));
260
      munmap(fpgamem, getpagesize());
261
      return (-1);
262
    }
263
  }
264

    
265
  // return -1; //Debug dont load new fpga
266

    
267

    
268
  // Get file size
269
  fseek(file, 0L, SEEK_END);
270
  filesize = ftell(file);
271
  printf("filesize %ld\n",filesize);
272
  filesize = filesize - offset;
273
  if (filesize < 0)
274
  {
275
    printf("Error reading fpga filesize\n");
276
    munmap(mpGpioRegs, sizeof(tsGpioRegs));
277
    munmap(fpgamem, getpagesize());
278
    return (errno);
279
  }
280

    
281
  // Verify max filesize
282
  if (filesize > (4 * 1024 * 1024))
283
  {
284
    printf("Error too large fpga filesize, max. 4MB\n");
285
    munmap(mpGpioRegs, sizeof(tsGpioRegs));
286
    munmap(fpgamem, getpagesize());
287
    return (-1);
288
  }
289

    
290
  // Verify in filesize
291
  if (filesize < (200 * 1024))
292
  {
293
    printf("FPGA Bin file too small\n");
294
    munmap(mpGpioRegs, sizeof(tsGpioRegs));
295
    munmap(fpgamem, getpagesize());
296
    return (-1);
297
  }
298

    
299
  // Allocate memory for file
300
  filedata = (uint8_t*) malloc(filesize);
301
  if (filedata == NULL)
302
  {
303
    printf("Error allocating memory for fpga file\n");
304
    munmap(mpGpioRegs, sizeof(tsGpioRegs));
305
    munmap(fpgamem, getpagesize());
306
    return (-1);
307
  }
308

    
309
  // Read fpga file
310
  fseek(file, offset, SEEK_SET);
311
  if (fread(filedata, 1, filesize, file) != (size_t) filesize)
312
  {
313
    printf("Error reading fpga file\n");
314
    free(filedata);
315
    munmap(mpGpioRegs, sizeof(tsGpioRegs));
316
    munmap(fpgamem, getpagesize());
317
    return (-1);
318
  }
319

    
320
  // Close file
321
  fclose(file);
322

    
323
  // Initialize fpga interface gpios
324
  GPIO_Init();
325

    
326
  // Reset fpga TPROGRAM low pulse time, must be above 500ns, hmmm we are way over the top here
327
  FPGA_ResetEnable();
328
  OSAL_TaskSleep(OSAL_SEC_TO_TICK(0.01));
329

    
330
  // Stop resetting
331
  FPGA_ResetDisable();
332
  OSAL_TaskSleep(OSAL_SEC_TO_TICK(0.01));
333

    
334
  // Verify reset OK
335
  if (FPGA_InitResponse() == 0)
336
  {
337
    printf("FPGA reset timeout\n");
338
    free(filedata);
339
    munmap(mpGpioRegs, sizeof(tsGpioRegs));
340
    munmap(fpgamem, getpagesize());
341
    return (-1);
342
  }
343

    
344
  // Read 32bit pattern 55 99 AA 66, if AA 99 55 66 we need to bit swap, else abort
345
  switch (*((uint32_t*) &filedata[0x10]))
346
  {
347
    case 0x665599AA:   // actually => 0xAA995566
348
      boBitSwap = True;
349
      break;
350

    
351
    // Already swapped
352
    case 0x66AA9955:   // actually => 0x5599AA66
353
    default:
354
      boBitSwap = False;
355
      break;
356
  }
357

    
358
  // Enable writing program to fpga
359
  FPGA_WriteEnable();
360
  OSAL_TaskSleep(OSAL_SEC_TO_TICK(0.01));
361

    
362
  // Send program to fpga
363
  for (i = 0; i < filesize; i++)
364
  {
365
     byte_t bIn = filedata[i];
366
     byte_t bOut = 0;
367
     int bit;
368

    
369
     if (boBitSwap)
370
     {
371
       for (bit = 0; bit <= 7; bit++)
372
       {
373
         bOut <<= 1;
374
         bOut |= (bIn & 0x01);
375
         bIn >>= 1;
376
       }
377
     }
378
     else
379
     {
380
       bOut = bIn;
381
     }
382
     *fpgamem = bOut;
383
  }
384

    
385
  // Done programming
386
  FPGA_WriteDisable();
387
  OSAL_TaskSleep(OSAL_SEC_TO_TICK(0.01));
388

    
389
  // Verify programming done (CRC) ok
390
  if (FPGA_InitResponse() == 0)
391
  {
392
    printf("FPGA programming failed\n");
393
    free(filedata);
394
    return (-1);
395
  }
396

    
397
  // Cleanup
398
  munmap(fpgamem, getpagesize());
399
  munmap(mpGpioRegs, sizeof(tsGpioRegs));
400
  free(filedata);
401

    
402
  return 0;
403
}
    (1-1/1)
    Go to top
    Add picture from clipboard (Maximum size: 1 GB)