OpenCores
URL https://opencores.org/ocsvn/neo430/neo430/trunk

Subversion Repositories neo430

[/] [neo430/] [trunk/] [neo430/] [sw/] [bootloader/] [bootloader.c] - Blame information for rev 198

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 198 zero_gravi
// #################################################################################################
2
// #  < NEO430 Bootloader >                                                                        #
3
// # ********************************************************************************************* #
4
// # Boot from IMEM, UART or SPI Flash at SPI.CS[0]                                                #
5
// #                                                                                               #
6
// # UART configuration: 8N1 at 19200 baud                                                         #
7
// # Boot Flash: 8-bit SPI, 24-bit addresses (like Micron N25Q032A) @ NEO430_SPI.CS[0]             #
8
// # NEO430_GPIO.out[0] is used as high-active status LED                                          #
9
// #                                                                                               #
10
// # Auto boot sequence after timeout:                                                             #
11
// #  -> Try booting from SPI flash at SPI.CS[0]                                                   #
12
// #  -> Permanently light up status led and freeze if SPI flash booting attempt fails             #
13
// # ********************************************************************************************* #
14
// # BSD 3-Clause License                                                                          #
15
// #                                                                                               #
16
// # Copyright (c) 2020, Stephan Nolting. All rights reserved.                                     #
17
// #                                                                                               #
18
// # Redistribution and use in source and binary forms, with or without modification, are          #
19
// # permitted provided that the following conditions are met:                                     #
20
// #                                                                                               #
21
// # 1. Redistributions of source code must retain the above copyright notice, this list of        #
22
// #    conditions and the following disclaimer.                                                   #
23
// #                                                                                               #
24
// # 2. Redistributions in binary form must reproduce the above copyright notice, this list of     #
25
// #    conditions and the following disclaimer in the documentation and/or other materials        #
26
// #    provided with the distribution.                                                            #
27
// #                                                                                               #
28
// # 3. Neither the name of the copyright holder nor the names of its contributors may be used to  #
29
// #    endorse or promote products derived from this software without specific prior written      #
30
// #    permission.                                                                                #
31
// #                                                                                               #
32
// # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS   #
33
// # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF               #
34
// # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE    #
35
// # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,     #
36
// # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
37
// # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED    #
38
// # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING     #
39
// # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED  #
40
// # OF THE POSSIBILITY OF SUCH DAMAGE.                                                            #
41
// # ********************************************************************************************* #
42
// # The NEO430 Processor - https://github.com/stnolting/neo430                                    #
43
// #################################################################################################
44
 
45
// Libraries
46
#include <stdint.h>
47
#include <neo430.h>
48
 
49
// SPI flash: NEO430 boot base address
50
#define SPI_FLASH_BOOT_ADR  0x00040000L
51
 
52
// Configuration
53
#define BAUD_RATE        19200 // default UART baud rate
54
#define AUTOBOOT_TIMEOUT 4     // countdown (seconds) to auto boot
55
#define STATUS_LED       0     // GPIO.out(0) is status LED
56
 
57
// SPI flash hardware configuration
58
#define SPI_FLASH_CS     0
59
 
60
// SPI flash commands
61
#define SPI_FLASH_CMD_READ           0x03
62
#define SPI_FLASH_CMD_READ_STATUS    0x05
63
#define SPI_FLASH_CMD_WRITE_ENABLE   0x06
64
#define SPI_FLASH_CMD_PAGE_PROGRAM   0x02
65
#define SPI_FLASH_CMD_SECTOR_ERASE   0xD8
66
#define SPI_FLASH_CMD_READ_ID        0x9E
67
#define SPI_FLASH_CMD_POWER_DOWN     0xB9
68
#define SPI_FLASH_CMD_RELEASE        0xAB
69
 
70
// Image sources
71
#define UART_IMAGE       0x00
72
#define EEPROM_IMAGE_SPI 0x01
73
 
74
// Error codes
75
#define ERROR_EEPROM     0x00 // EEPROM access error
76
#define ERROR_ROMACCESS  0x01 // cannot write to IMEM
77
#define ERROR_EXECUTABLE 0x02 // invalid executable format
78
#define ERROR_SIZE       0x04 // executable is too big
79
#define ERROR_CHECKSUM   0x08 // checksum error
80
 
81
// Scratch registers - abuse unused IRQ vectors for this ;)
82
#define TIMEOUT_CNT IRQVEC_GPIO
83
 
84
// Macros
85
#define xstr(a) str(a)
86
#define str(a) #a
87
#define SPI_FLASH_SEL {SPI_CT |= 1 << (SPI_FLASH_CS+SPI_CT_CS_SEL0);}
88
 
89
// Function prototypes
90
void     __attribute__((__interrupt__)) timer_irq_handler(void);
91
void     __attribute__((__naked__)) start_app(void);
92
void     print_help(void);
93
void     store_eeprom(void);
94
void     eeprom_write_word(uint32_t a, uint16_t d);
95
void     get_image(uint8_t src);
96
uint16_t get_image_word(uint32_t a, uint8_t src);
97
void     __attribute__((__naked__)) system_error(uint8_t err_code);
98
 
99
// Function prototypes - SPI flash
100
uint8_t spi_flash_read_byte();
101
void    spi_flash_write_byte(uint32_t adr, uint8_t data);
102
void    spi_flash_erase_sector(uint32_t base_adr);
103
uint8_t spi_flash_read_status(void);
104
void    spi_flash_write_cmd(uint16_t cmd);
105
uint8_t spi_flash_read_1st_id(void);
106
void    spi_flash_adr_conv(uint32_t adr, uint16_t *hi, uint16_t *mi, uint16_t *lo);
107
 
108
 
109
/* ------------------------------------------------------------
110
 * INFO Bootloader main
111
 * ------------------------------------------------------------ */
112
int main(void) {
113
 
114
  // ****************************************************************
115
  // Processor hardware initialization
116
  // ****************************************************************
117
 
118
  // stack setup
119
  // -> done in boot_crt0
120
 
121
  // disable watchdog timer
122
  neo430_wdt_disable();
123
 
124
  // clear status register and disable interrupts, clear interrupt buffer, enable write access to IMEM
125
  asm volatile ("mov %0, r2" : : "i" ((1<<R_FLAG) | (1<<Q_FLAG)));
126
 
127
  // disable TRNG
128
  TRNG_CT = 0;
129
 
130
  // disable Wishbone interface
131
  WB32_CT = 0;
132
 
133
  // disable PWM
134
  PWM_CT = 0;
135
 
136
  // disable TWI
137
  TWI_CT = 0;
138
 
139
  // disable EXIRQ
140
  EXIRQ_CT = 0;
141
 
142
  // disable FREQ_GEN
143
  FREQ_GEN_CT = 0;
144
 
145
  // init GPIO
146
  GPIO_IRQMASK = 0; // no pin change interrupt please, thanks
147
  neo430_gpio_port_set(1<<STATUS_LED); // activate status LED, clear all others
148
 
149
  // init interrupt vectors
150
  IRQVEC_TIMER  = (uint16_t)(&timer_irq_handler); // timer match
151
//IRQVEC_EXT    = 0; // unused
152
//IRQVEC_SERIAL = 0; // unused
153
 
154
  // set Baud rate & init UART control register:
155
  // enable UART, no IRQs
156
  neo430_uart_setup(BAUD_RATE);
157
  neo430_uart_char_read(); // clear UART RX buffer
158
 
159
  // set SPI config:
160
  // enable SPI, no IRQ, MSB first, 8-bit mode, SPI clock mode 0, set SPI speed, disable all SPI CS lines (set high)
161
  neo430_spi_enable(SPI_PRSC_8); // this also resets the SPI module
162
 
163
  // Timeout counter: init timer, irq tick @ ~1Hz (prescaler = 4096)
164
  // THR = f_main / (1Hz + 4096) -1
165
  TMR_CT = 0; // reset timer
166
  //uint32_t clock = CLOCKSPEED_32bit >> 14; // divide by 4096
167
  TMR_THRES = (CLOCKSPEED_HI << 2) -1; // "fake" ;D
168
  // enable timer, auto reset, enable IRQ, prsc = 1:2^16, start timer
169
  TMR_CT = (1<<TMR_CT_EN) | (1<<TMR_CT_ARST) | (1<<TMR_CT_IRQ) | ((16-1)<<TMR_CT_PRSC0) | (1<<TMR_CT_RUN);
170
  TIMEOUT_CNT = 0; // console timeout ticker
171
 
172
  neo430_eint(); // enable global interrupts
173
 
174
 
175
  // ****************************************************************
176
  // Show bootloader intro and system information
177
  // ****************************************************************
178
  neo430_uart_br_print("\n\nNEO430 Bootloader\n"
179
                       "\n"
180
                       "BLV: "__DATE__"\n"
181
                       "HWV: 0x");
182
  neo430_uart_print_hex_word(HW_VERSION);
183
  neo430_uart_br_print("\nUSR: 0x");
184
  neo430_uart_print_hex_word(USER_CODE);
185
  neo430_uart_br_print("\nCLK: 0x");
186
  neo430_uart_print_hex_word(CLOCKSPEED_HI);
187
  neo430_uart_print_hex_word(CLOCKSPEED_LO);
188
  neo430_uart_br_print("\nROM: 0x");
189
  neo430_uart_print_hex_word(IMEM_SIZE);
190
  neo430_uart_br_print("\nRAM: 0x");
191
  neo430_uart_print_hex_word(DMEM_SIZE);
192
  neo430_uart_br_print("\nSYS: 0x");
193
  neo430_uart_print_hex_word(SYS_FEATURES);
194
 
195
 
196
  // get SPI flash out of power down mode
197
  spi_flash_write_cmd((uint16_t)SPI_FLASH_CMD_RELEASE);
198
 
199
 
200
  // ****************************************************************
201
  // Auto boot sequence
202
  // ****************************************************************
203
  neo430_uart_br_print("\n\nAutoboot in "xstr(AUTOBOOT_TIMEOUT)"s. Press key to abort.\n\n");
204
  while (1) { // wait for any key to be pressed or timeout
205
 
206
    // timeout? start auto boot sequence
207
    if (TIMEOUT_CNT == 4*AUTOBOOT_TIMEOUT) { // in 0.25 seconds
208
      get_image(EEPROM_IMAGE_SPI); // try loading from EEPROM
209
      neo430_uart_br_print("\n");
210
      start_app(); // start app
211
    }
212
 
213
    // key pressed? -> enter user console
214
    if ((UART_RTX & (1<<UART_RTX_AVAIL)) != 0) {
215
      break;
216
    }
217
  }
218
  print_help();
219
 
220
 
221
  // ****************************************************************
222
  // Bootloader console
223
  // ****************************************************************
224
  while (1) {
225
 
226
    neo430_uart_br_print("\nCMD:> ");
227
    char c = neo430_uart_getc();
228
    neo430_uart_putc(c); // echo
229
    neo430_uart_br_print("\n");
230
 
231
    if (c == 'r') { // restart bootloader
232
      asm volatile ("mov #0xF000, r0"); // jump to beginning of bootloader ROM
233
    }
234
    else if (c == 'h') { // help menu
235
      print_help();
236
    }
237
    else if (c == 'u') { // upload program to RAM via UART
238
      get_image(UART_IMAGE);
239
    }
240
    else if (c == 'p') { // program EEPROM from RAM
241
      store_eeprom();
242
    }
243
    else if (c == 'e') { // start program in RAM
244
      start_app();
245
    }
246
    else { // unknown command
247
      neo430_uart_br_print("Bad CMD");
248
    }
249
  }
250
}
251
 
252
 
253
/* ------------------------------------------------------------
254
 * INFO Timer IRQ handler
255
 * ------------------------------------------------------------ */
256
void __attribute__((__interrupt__)) timer_irq_handler(void) {
257
 
258
  TIMEOUT_CNT++; // increment system ticker
259
  neo430_gpio_port_toggle(1<<STATUS_LED); // toggle status LED
260
}
261
 
262
 
263
/* ------------------------------------------------------------
264
 * INFO Start application in IMEM
265
 * INFO "naked" since this is final...
266
 * ------------------------------------------------------------ */
267
void __attribute__((__naked__)) start_app(void) {
268
 
269
  // put SPI flah into power-down mode
270
  spi_flash_write_cmd((uint16_t)SPI_FLASH_CMD_POWER_DOWN);
271
 
272
  neo430_uart_br_print("Booting...\n\n");
273
 
274
  // wait for UART to finish transmitting
275
  while ((UART_CT & (1<<UART_CT_TX_BUSY)) != 0);
276
 
277
  // deactivate IRQs, no more write access to IMEM, clear all pending IRQs
278
  asm volatile ("mov %0, r2" : : "i" (1<<Q_FLAG));
279
 
280
  // start app in IMEM at address 0x0000
281
  while (1) {
282
    asm volatile ("mov #0x0000, r0");
283
  }
284
}
285
 
286
 
287
/* ------------------------------------------------------------
288
 * INFO Print help text
289
 * ------------------------------------------------------------ */
290
void print_help(void) {
291
 
292
  neo430_uart_br_print("CMDs:\n"
293
                       "h: Help\n"
294
                       "r: Restart\n"
295
                       "u: Upload\n"
296
                       "p: Prog\n"
297
                       "e: Execute");
298
}
299
 
300
 
301
/* ------------------------------------------------------------
302
 * INFO Store full IMEM content to SPI EEPROM at SPI.CS0
303
 * ------------------------------------------------------------ */
304
void store_eeprom(void) {
305
 
306
  neo430_uart_br_print("...");
307
 
308
  // clear memory before writing
309
  spi_flash_erase_sector(SPI_FLASH_BOOT_ADR);
310
 
311
  // check if eeprom ready (or available at all)
312
  if (spi_flash_read_1st_id() == 0x00) { // manufacturer ID
313
    system_error(ERROR_EEPROM);
314
  }
315
 
316
  // write EXE signature
317
  eeprom_write_word(SPI_FLASH_BOOT_ADR + 0, 0xCAFE);
318
 
319
  // write size
320
  uint16_t end = IMEM_SIZE;
321
  eeprom_write_word(SPI_FLASH_BOOT_ADR + 2, end);
322
 
323
  // store data from IMEM and update checksum
324
  uint16_t checksum = 0;
325
  uint16_t i = 0;
326
  uint16_t *pnt = (uint16_t*)0x0000;
327
 
328
  while (i < end) {
329
    uint16_t d = (uint16_t)*pnt++;
330
    checksum ^= d;
331
    eeprom_write_word(SPI_FLASH_BOOT_ADR + 6 + i, d);
332
    i+= 2;
333
  }
334
 
335
  // write checksum
336
  eeprom_write_word(SPI_FLASH_BOOT_ADR + 4, checksum);
337
 
338
  neo430_uart_br_print("OK");
339
}
340
 
341
 
342
/* ------------------------------------------------------------
343
 * INFO EEPROM write data word
344
 * PARAM a destination address (24 bit effective)
345
 * PARAM d word to be written
346
 * ------------------------------------------------------------ */
347
void eeprom_write_word(uint32_t a, uint16_t d) {
348
 
349
  uint8_t lo = (uint8_t)(d);
350
  uint8_t hi = (uint8_t)neo430_bswap(d);
351
 
352
  spi_flash_write_byte(a+0, hi);
353
  spi_flash_write_byte(a+1, lo);
354
}
355
 
356
 
357
/* ------------------------------------------------------------
358
 * INFO Get IMEM image from SPI EEPROM at SPI.CS0 or from UART
359
 * PARAM src Image source 0: UART, 1: SPI_EEPROM
360
 * RETURN error code (0 if successful)
361
 * ------------------------------------------------------------ */
362
void get_image(uint8_t src) {
363
 
364
  // abort if IMEM was implemented as true ROM
365
  if (SYS_FEATURES & (1<<SYS_IROM_EN)) {
366
    system_error(ERROR_ROMACCESS);
367
  }
368
 
369
  // print intro
370
  if (src == UART_IMAGE) { // boot via UART
371
    neo430_uart_br_print("Awaiting BINEXE...");
372
  }
373
  else { //if (src == EEPROM_IMAGE_SPI)// boot from EEPROM
374
    neo430_uart_br_print("Loading...");
375
  }
376
 
377
  // check if valid image
378
  if (get_image_word(SPI_FLASH_BOOT_ADR + 0, src) != 0xCAFE) { // signature
379
    system_error(ERROR_EXECUTABLE);
380
  }
381
 
382
  // image size and checksum
383
  uint16_t size = get_image_word(SPI_FLASH_BOOT_ADR + 2, src); // size in bytes
384
  uint16_t check = get_image_word(SPI_FLASH_BOOT_ADR + 4, src); // XOR checksum
385
  uint16_t end = IMEM_SIZE;
386
  if (size > end) {
387
    system_error(ERROR_SIZE);
388
  }
389
 
390
  // transfer program data
391
  uint16_t *pnt = (uint16_t*)0x0000;
392
  uint16_t checksum = 0x0000;
393
  uint16_t d = 0, i = 0;
394
  while (i < size/2) { // in words
395
    d = get_image_word(SPI_FLASH_BOOT_ADR + 2*i + 6, src);
396
    checksum ^= d;
397
    pnt[i++] = d;
398
  }
399
 
400
  // clear rest of IMEM
401
  while(i < end/2) { // in words
402
    pnt[i++] = 0x0000;
403
  }
404
 
405
  // error during transfer?
406
  if (checksum == check) {
407
    neo430_uart_br_print("OK");
408
  }
409
  else {
410
    system_error(ERROR_CHECKSUM);
411
  }
412
}
413
 
414
 
415
/* ------------------------------------------------------------
416
 * INFO Get image word from SPI_EEPROM or UART
417
 * PARAM a source address (24 bit effective)
418
 * PARAM src: 0: UART, 1: SPI_EEPROM
419
 * RETURN accessed data word
420
 * ------------------------------------------------------------ */
421
uint16_t get_image_word(uint32_t a, uint8_t src) {
422
 
423
  uint8_t c0 = 0, c1 = 0;
424
 
425
  // reads have to be consecutive when reading from the UART
426
  if (src == UART_IMAGE) { // get image data via UART
427
    c0 = (uint8_t)neo430_uart_getc();
428
    c1 = (uint8_t)neo430_uart_getc();
429
  }
430
  else {// if (src == EEPROM_IMAGE_SPI) { // get image data from SPI EEPROM
431
    c0 = spi_flash_read_byte(a+0);
432
    c1 = spi_flash_read_byte(a+1);
433
  }
434
 
435
  //uint16_t r = (((uint16_t)c0) << 8) | (((uint16_t)c1) << 0);
436
  uint16_t r = neo430_combine_bytes(c0, c1);
437
 
438
  return r;
439
}
440
 
441
 
442
/* ------------------------------------------------------------
443
 * INFO Print error message, light up status LED and freeze system
444
 * INFO "naked" since this is final
445
 * PARAM error code
446
 * ------------------------------------------------------------ */
447
void __attribute__((__naked__)) system_error(uint8_t err_code){
448
 
449
  neo430_uart_br_print("\a\nERR_"); // output error code with annoying bell sound
450
  neo430_uart_print_hex_byte(err_code);
451
 
452
  asm volatile ("mov #0, r2"); // deactivate IRQs, no more write access to IMEM
453
  neo430_gpio_port_set(1<<STATUS_LED); // permanently light up status LED
454
 
455
  while(1); // freeze
456
}
457
 
458
 
459
 
460
// *************************************************************************************
461
// SPI flash functions
462
// *************************************************************************************
463
 
464
/* ------------------------------------------------------------
465
 * Read single byte from flash (24-bit adress)
466
 * ------------------------------------------------------------ */
467
uint8_t spi_flash_read_byte(uint32_t adr) {
468
 
469
  uint16_t adr_lo;
470
  uint16_t adr_mi;
471
  uint16_t adr_hi;
472
  spi_flash_adr_conv(adr, &adr_hi, &adr_mi, &adr_lo);
473
 
474
  SPI_FLASH_SEL;
475
 
476
  neo430_spi_trans((uint16_t)SPI_FLASH_CMD_READ);
477
  // no masking required, SPI unit in 8 bit mode ignores upper 8 bits
478
  neo430_spi_trans(adr_hi);
479
  neo430_spi_trans(adr_mi);
480
  neo430_spi_trans(adr_lo);
481
  uint16_t data = neo430_spi_trans(0);
482
 
483
  neo430_spi_cs_dis();
484
 
485
  return (uint8_t)data;
486
}
487
 
488
 
489
/* ------------------------------------------------------------
490
 * Write single data byte to flash at base adress
491
 * ------------------------------------------------------------ */
492
void spi_flash_write_byte(uint32_t adr, uint8_t data) {
493
 
494
  uint16_t adr_lo;
495
  uint16_t adr_mi;
496
  uint16_t adr_hi;
497
  spi_flash_adr_conv(adr, &adr_hi, &adr_mi, &adr_lo);
498
 
499
  spi_flash_write_cmd((uint16_t)SPI_FLASH_CMD_WRITE_ENABLE); // allow write-access
500
 
501
  SPI_FLASH_SEL;
502
 
503
  neo430_spi_trans((uint16_t)SPI_FLASH_CMD_PAGE_PROGRAM);
504
  // no masking required, SPI unit in 8 bit mode ignores upper 8 bits
505
  neo430_spi_trans(adr_hi);
506
  neo430_spi_trans(adr_mi);
507
  neo430_spi_trans(adr_lo);
508
  neo430_spi_trans((uint16_t)data);
509
 
510
  neo430_spi_cs_dis();
511
 
512
  while(spi_flash_read_status());
513
}
514
 
515
 
516
/* ------------------------------------------------------------
517
 * Erase sector (64kB) at base adress
518
 * ------------------------------------------------------------ */
519
void spi_flash_erase_sector(uint32_t base_adr) {
520
 
521
  uint16_t adr_lo;
522
  uint16_t adr_mi;
523
  uint16_t adr_hi;
524
  spi_flash_adr_conv(base_adr, &adr_hi, &adr_mi, &adr_lo);
525
 
526
  spi_flash_write_cmd((uint16_t)SPI_FLASH_CMD_WRITE_ENABLE); // allow write-access
527
 
528
  SPI_FLASH_SEL;
529
 
530
  neo430_spi_trans((uint16_t)SPI_FLASH_CMD_SECTOR_ERASE);
531
  // no masking required, SPI unit in 8 bit mode ignores upper 8 bits
532
  neo430_spi_trans(adr_hi);
533
  neo430_spi_trans(adr_mi);
534
  neo430_spi_trans(adr_lo);
535
 
536
  neo430_spi_cs_dis();
537
 
538
  while(spi_flash_read_status());
539
}
540
 
541
 
542
/* ------------------------------------------------------------
543
 * Read status register
544
 * ------------------------------------------------------------ */
545
uint8_t spi_flash_read_status(void) {
546
 
547
  SPI_FLASH_SEL;
548
 
549
  neo430_spi_trans((uint16_t)SPI_FLASH_CMD_READ_STATUS);
550
  uint16_t status = neo430_spi_trans(0);
551
 
552
  neo430_spi_cs_dis();
553
 
554
  return (uint8_t)status;
555
}
556
 
557
 
558
/* ------------------------------------------------------------
559
 * Read first byte of ID (manufacturer ID), should be != 0x00
560
 * ------------------------------------------------------------ */
561
uint8_t spi_flash_read_1st_id(void) {
562
 
563
  SPI_FLASH_SEL;
564
 
565
  neo430_spi_trans((uint16_t)SPI_FLASH_CMD_READ_ID);
566
  uint16_t id = neo430_spi_trans(0);
567
 
568
  neo430_spi_cs_dis();
569
 
570
  return (uint8_t)id;
571
}
572
 
573
 
574
/* ------------------------------------------------------------
575
 * Write command to flash
576
 * ------------------------------------------------------------ */
577
void spi_flash_write_cmd(uint16_t cmd) {
578
 
579
  SPI_FLASH_SEL;
580
 
581
  neo430_spi_trans(cmd);
582
 
583
  neo430_spi_cs_dis();
584
}
585
 
586
 
587
/* ------------------------------------------------------------
588
 * Adress conversion helper
589
 * ------------------------------------------------------------ */
590
void spi_flash_adr_conv(uint32_t adr, uint16_t *hi, uint16_t *mi, uint16_t *lo) {
591
 
592
  uint16_t adr_hi16 = (uint16_t)(adr >> 16);
593
  uint16_t adr_lo16 = (uint16_t)(adr >>  0);
594
 
595
  *lo = adr_lo16;
596
  *mi = neo430_bswap(adr_lo16);
597
  *hi = adr_hi16;
598
}
599
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.