| LPCOpen Platform v1.03 LPCOpen Platform for NXP LPC Microcontrollers

- Main Page
- Modules
- Data Structures
- Files
- Related Pages

- File List
- Globals

All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
dfuutil_programming_dfu_ops.c
Go to the documentation of this file.
1 /*
2 * @brief DFU utility (programmer) streaming code
3 *
4 * @note
5 * Copyright(C) NXP Semiconductors, 2012
6 * All rights reserved.
7 *
8 * @par
9 * Software that is described herein is for illustrative purposes only
10 * which provides customers with programming information regarding the
11 * LPC products. This software is supplied "AS IS" without any warranties of
12 * any kind, and NXP Semiconductors and its licensor disclaim any and
13 * all warranties, express or implied, including all implied warranties of
14 * merchantability, fitness for a particular purpose and non-infringement of
15 * intellectual property rights. NXP Semiconductors assumes no responsibility
16 * or liability for the use of the software, conveys no license or rights under any
17 * patent, copyright, mask work right, or any other intellectual property rights in
18 * or to any products. NXP Semiconductors reserves the right to make changes
19 * in the software without notification. NXP Semiconductors also makes no
20 * representation or warranty that such application will be suitable for the
21 * specified use without further testing or modification.
22 *
23 * @par
24 * Permission to use, copy, modify, and distribute this software and its
25 * documentation is hereby granted, under NXP Semiconductors' and its
26 * licensor's relevant copyrights in the software, without fee, provided that it
27 * is used in conjunction with NXP Semiconductors microcontrollers. This
28 * copyright, permission, and disclaimer notice must appear in all copies of
29 * this code.
30 */
31
32 #include "app_usbd_cfg.h"
33 #include "usbd_desc.h"
34 #include "usbd_mscuser.h"
35 #include "usbd.h"
36 #include "usbd_core.h"
37 #include "usbd_hw.h"
38 #include "usbd_mscuser.h"
39 #include "usbd_rom_api.h"
40
41 #include "board.h"
42 #include "dfuutil_programming_api.h"
43
44 #include "string.h"
45
46 /*****************************************************************************
47 * Private types/enumerations/variables
48 ****************************************************************************/
49
50 /* USB handle for ROM driver */
51 static USBD_HANDLE_T hUsb;
52
53 /* Saved pointer to region data for programming algorithm */
54 static DFUPROG_REGION_T *dfuprog_regions;
55
56 /* Current status of the program and last host command */
57 static volatile uint32_t currStatus;
58 static volatile uint32_t hostCmd;
59
60 /* Address and size for the current command */
61 static volatile uint32_t currCmdAddr, currCmdSize;
62
63 /* Time counter in 1mS ticks */
64 static volatile uint32_t u32Milliseconds;
65
66 /* Size of USB debug message buffer */
67 #define USBMSGBUFFSIZE 1024
68
69 /* USB debug message buffer and pointers */
70 static char usbBuff[USBMSGBUFFSIZE];
71 static volatile int usbStrIn, usbStrOut;
72
73 /* Buffer for DFU output (to host) */
74 static uint32_t dfuIn[((sizeof(DFU_TOHOST_PACKETHDR_T) + 64 + 4096) /
75 sizeof(uint32_t))];
76
77 /* Buffer for DFU input (from host) */
78 static uint32_t dfuOut[((sizeof(DFU_FROMHOST_PACKETHDR_T) + 4096 +
79 sizeof(uint32_t)) / sizeof(uint32_t))];
80
81 /* Program data buffer (to free up USB buffer) */
82 static uint32_t dfuProgBuff[(4096 / sizeof(uint32_t))];
83
84 /* IN packet indexing and size */
85 static volatile uint32_t inPktSize, inPktSizeIdx, outPktSizeIdx, progSize;
86
87 /* Be careful with this number, as the linker may be setup to use ranges
88 just outside this area's size */
89 #define USBROMBUFFSIZE 0x2000
90
91 /* Temporary string buffer */
92 static char tmpStr[64];
93
94 /* Quiet mode flag, used with the parameter option to enable verbose
95 debug messages */
96 static bool verifyDebug = true;
97
98 /*****************************************************************************
99 * Public types/enumerations/variables
100 ****************************************************************************/
101
102 extern uint8_t USB_DeviceDescriptor[];
103 extern uint8_t USB_FsConfigDescriptor[];
104 extern uint8_t USB_HsConfigDescriptor[];
105 extern uint8_t USB_StringDescriptor[];
106 extern uint8_t USB_DeviceQualifier[];
107
108 volatile uint32_t dfu_done_algo = 0, dfu_detach_algo = 0;
109
110 /*****************************************************************************
111 * Private functions
112 ****************************************************************************/
113
114 /* Delay until ticks expired */
115 static void tickDelayMS(int ticks)
116 {
117 u32Milliseconds = ticks;
118 while (u32Milliseconds) {}
119 }
120
121 /* Sets up debug message buffering for USB status messages */
122 static void usbDebugSetup(void)
123 {
124 /* Just reset pointers to start of buffer */
125 usbStrIn = usbStrOut = 0;
126 }
127
128 /* Gets message data for a DFU status transfer */
129 static int usbDebugFill(void *buff, int max)
130 {
131 int ssize = 0;
132
133 if (usbStrIn != usbStrOut) {
134 /* Largest size to send is until the end of the buffer or
135 the passed maximum size */
136 if (usbStrOut > usbStrIn) {
137 /* Can send up to the end of the buffer */
138 ssize = USBMSGBUFFSIZE - usbStrOut;
139 }
140 else {
141 /* Can send up to the end of input */
142 ssize = usbStrIn - usbStrOut;
143 }
144
145 /* Limit size to input */
146 if (ssize > max) {
147 ssize = max;
148 }
149
150 /* Copy data */
151 memmove(buff, &usbBuff[usbStrOut], ssize);
152
153 /* Update start of output and next output index */
154 usbStrOut += ssize;
155 if (usbStrOut >= USBMSGBUFFSIZE) {
156 usbStrOut = 0;
157 }
158 }
159
160 return ssize;
161 }
162
163 /* Appends data to a USB buffer */
164 static int usbDFUAppend(char *ptr, void *data, uint32_t bytes)
165 {
166 memmove(ptr, data, bytes);
167
168 return bytes;
169 }
170
171 /* Build the response header */
172 static int usbDFUBuildStatus(void *buffer)
173 {
174 char *ptr = (char *) buffer;
175 int strbytes, rsvd, bytes;
176
177 /* Place string in buffer if needed */
178 strbytes = usbDebugFill((ptr + 16), 64);
179
180 /* Create header */
181 bytes = usbDFUAppend((ptr + 0), (void *) &hostCmd, 4);
182 bytes += usbDFUAppend((ptr + 4), (void *) &currStatus, 4);
183 bytes += usbDFUAppend((ptr + 8), &strbytes, 4);
184
185 /* Field is marked as reserved, but it is being used for the
186 DFU buffer size */
187 rsvd = dfuprog_regions->buffer_size;
188 bytes += usbDFUAppend((ptr + 12), &rsvd, 4);/* Reserved[1] field */
189
190 /* Allocate some space for debug message if needed */
191 if (strbytes != 0) {
192 bytes += 64;
193 }
194
195 return bytes;
196 }
197
198 /* Build programming algo status */
199 static int usbDFUReturnStatus(void *buffer)
200 {
201 return usbDFUBuildStatus(buffer);
202 }
203
204 /* Respond to DFU_HOSTCMD_SETDEBUG command */
205 static void usbDFUSetVerbose(uint32_t addr)
206 {
207 /* Set quiet or verbose mode based on address field */
208 hostCmd = DFU_HOSTCMD_SETDEBUG;
209
210 if (addr) {
211 verifyDebug = false;
212 }
213 else {
214 verifyDebug = true;
215 }
216 }
217
218 /* Respond to DFU_HOSTCMD_ERASE_ALL command */
219 static void usbDFUEraseAll(void)
220 {
221 /* Set erase start state so it starts in the background. */
222 currStatus = DFU_OPSTS_ERASE_ALL_ST;
223 hostCmd = DFU_HOSTCMD_ERASE_ALL;
224 }
225
226 /* Respond to DFU_HOSTCMD_ERASE_REGION command */
227 static void usbDFUEraseRegion(uint32_t addr, uint32_t size)
228 {
229 /* Set erase start state so it starts in the background. */
230 currStatus = DFU_OPSTS_ERASE_ST;
231 hostCmd = DFU_HOSTCMD_ERASE_REGION;
232
233 /* Save erase address and size */
234 currCmdAddr = addr;
235 currCmdSize = size;
236 }
237
238 /* Respond to DFU_HOSTCMD_PROGRAM command */
239 static void usbDFUProgRegion(uint32_t addr, uint32_t size)
240 {
241 /* Set erase start state so it starts in the background. */
242 currStatus = DFU_OPSTS_PROG_STREAM;
243 hostCmd = DFU_HOSTCMD_PROGRAM;
244
245 /* Save program address and size */
246 currCmdAddr = addr;
247 currCmdSize = size;
248 }
249
250 /* Respond to DFU_HOSTCMD_READBACK command */
251 static void usbDFUReadRegion(uint32_t addr, uint32_t size)
252 {
253 /* Set erase start state so it starts in the background. */
254 currStatus = DFU_OPSTS_READBUSY;
255 hostCmd = DFU_HOSTCMD_READBACK;
256
257 /* Save read address and size */
258 currCmdAddr = addr;
259 currCmdSize = size;
260 }
261
262 /* Respond to DFU_HOSTCMD_RESET command */
263 static void usbDFUReset(void)
264 {
265 /* Will reset in background. */
266 currStatus = DFU_OPSTS_RESET;
267 hostCmd = DFU_HOSTCMD_RESET;
268 }
269
270 /* Respond to DFU_HOSTCMD_EXECUTE command */
271 static void usbDFUExecute(uint32_t addr)
272 {
273 /* Will reset in background. */
274 currStatus = DFU_OPSTS_EXEC;
275 hostCmd = DFU_HOSTCMD_EXECUTE;
276
277 currCmdAddr = addr;
278 }
279
280 /* Will set dfu_detach_algo flag when USB detaches */
281 static void dfu_detach(USBD_HANDLE_T hUsb)
282 {
283 dfu_detach_algo = 1;
284 }
285
286 /* Will set dfu_done_algo flag when USB DFU download is complete (ZLP received) */
287 static void dfu_done(void)
288 {
289 dfu_done_algo = 1;
290 }
291
292 void USB0_IRQHandler(void)
293 {
294 USBD_API->hw->ISR(hUsb);
295 }
296
297 void USB1_IRQHandler(void)
298 {
299 USBD_API->hw->ISR(hUsb);
300 }
301
302 /* Checks header */
303 static bool checkMagicHeader(DFU_FROMHOST_PACKETHDR_T *pOutHdr)
304 {
305 bool checked = false;
306
307 if ((pOutHdr->magic != DFUPROG_VALIDVAL) && (checked == false)) {
308 /* Let it keep running, but send a warning */
309 usbDebug("DFU Utility and programming algorithm have different versions\n");
310 checked = true;
311 }
312
313 return true;
314 }
315
316 /* Handles OUT (from host) packets and requests from host */
317 static uint8_t dfu_wr(uint32_t block_num, uint8_t * *pBuff, uint32_t length,
318 uint8_t *bwPollTimeout)
319 {
320 DFU_FROMHOST_PACKETHDR_T *pOutHdr;
321 uint32_t addr, size;
322
323 /* Reset buffer on length = 0 */
324 if (length != 0) {
325 /* Concatenate packets */
326 *pBuff += length;
327 outPktSizeIdx += length;
328 }
329
330 /* Hack for no ZLP on end of aligned DFU transfer */
331 if (currStatus == DFU_OPSTS_PROG_STREAM) {
332 if (length == 0) {
333 outPktSizeIdx = 0;
334 *pBuff = (uint8_t *) dfuProgBuff;
335 }
336 else if ((outPktSizeIdx == dfuprog_regions->buffer_size) ||
337 (outPktSizeIdx == currCmdSize)) {
338 currStatus = DFU_OPSTS_PROG;
339 progSize = outPktSizeIdx;
340 currCmdSize -= outPktSizeIdx;
341 outPktSizeIdx = 0;
342 *pBuff = (uint8_t *) dfuIn;
343 }
344 }
345 else if (length != 0) {
346 /* Parse packet header, not necessarily used on all receives */
347 pOutHdr = (DFU_FROMHOST_PACKETHDR_T *) dfuIn;
348 addr = pOutHdr->addr;
349 size = pOutHdr->size;
350 checkMagicHeader(pOutHdr);
351
352 /* Process based on current state */
353 switch (pOutHdr->hostCmd) {
354 case DFU_HOSTCMD_SETDEBUG:
355 usbDFUSetVerbose(addr);
356 break;
357
358 case DFU_HOSTCMD_ERASE_ALL:
359 usbDFUEraseAll();
360 break;
361
362 case DFU_HOSTCMD_ERASE_REGION:
363 usbDFUEraseRegion(addr, size);
364 break;
365
366 case DFU_HOSTCMD_PROGRAM:
367 /* Only called in stream mode */
368 usbDFUProgRegion(addr, size);
369 outPktSizeIdx = 0;
370 *pBuff = (uint8_t *) dfuProgBuff;
371 return DFU_STATUS_OK;
372
373 case DFU_HOSTCMD_READBACK:
374 usbDFUReadRegion(addr, size);
375 break;
376
377 case DFU_HOSTCMD_RESET:
378 usbDFUReset();
379 break;
380
381 case DFU_HOSTCMD_EXECUTE:
382 usbDFUExecute(addr);
383 break;
384
385 default:
386 /* Unknown */
387 usbDebug("Unknown command\n");
388 currStatus = DFU_OPSTS_ERRUN;
389 break;
390 }
391
392 outPktSizeIdx = 0;
393 *pBuff = (uint8_t *) dfuIn;
394 }
395 else {
396 outPktSizeIdx = 0;
397 *pBuff = (uint8_t *) dfuIn;
398 }
399
400 return DFU_STATUS_OK;
401 }
402
403 /* DFU IN (to host) state machine for status polling */
404 static uint32_t dfu_rd(uint32_t block_num, uint8_t * *pBuff, uint32_t length)
405 {
406 uint8_t *pBuf = (uint8_t *) *pBuff;
407 uint8_t *ptrCurr;
408
409 if (length == 0) {
410 inPktSize = 0;
411 }
412
413 /* Task based on current state */
414 switch (currStatus) {
415 case DFU_OPSTS_IDLE:
416 case DFU_OPSTS_ERRER:
417 case DFU_OPSTS_PROGER:
418 case DFU_OPSTS_READER:
419 case DFU_OPSTS_ERRUN:
420 case DFU_OPSTS_READBUSY:
421 case DFU_OPSTS_READTRIG:
422 case DFU_OPSTS_ERASE_ALL_ST:
423 case DFU_OPSTS_ERASE_ST:
424 case DFU_OPSTS_ERASE:
425 case DFU_OPSTS_PROG:
426 case DFU_OPSTS_PROG_STREAM:
427 case DFU_OPSTS_RESET:
428 case DFU_OPSTS_EXEC:
429 case DFU_OPSTS_LOOP:
430 /* All these states return only status */
431 if (inPktSize == 0) {
432 /* Build status response */
433 inPktSize = usbDFUReturnStatus((void *) dfuOut);
434 inPktSizeIdx = 0;
435 ptrCurr = (uint8_t *) dfuOut;
436 }
437
438 if (inPktSize != 0) {
439 if (length > inPktSize) {
440 length = inPktSize;
441 }
442
443 if (currStatus == DFU_OPSTS_READTRIG) {
444 /* Switch to read ready state on trnasfer completion */
445 currStatus = DFU_OPSTS_READREADY;
446 }
447
448 memmove(pBuf, &ptrCurr[inPktSizeIdx], length);
449 inPktSize -= length;
450 inPktSizeIdx += length;
451 }
452 break;
453
454 case DFU_OPSTS_READREADY:
455 if (inPktSize == 0) {
456 inPktSize = currCmdSize;
457 if (inPktSize > dfuprog_regions->buffer_size) {
458 inPktSize = dfuprog_regions->buffer_size;
459 }
460 currCmdSize -= inPktSize;
461 inPktSizeIdx = 0;
462 ptrCurr = (uint8_t *) dfuProgBuff;
463 }
464
465 if (inPktSize != 0) {
466 if (length > inPktSize) {
467 length = inPktSize;
468 }
469
470 memmove(pBuf, &ptrCurr[inPktSizeIdx], length);
471 inPktSize -= length;
472 inPktSizeIdx += length;
473 }
474
475 if (inPktSize == 0) {
476 /* Next block */
477 if (currCmdSize == 0) {
478 /* Done with transfer */
479 currStatus = DFU_OPSTS_IDLE;
480 }
481 else {
482 currStatus = DFU_OPSTS_READBUSY;
483 }
484 }
485 break;
486
487 default:
488 /* No other cases */
489 usbDebug("Bad programming algorithm state\n");
490 currStatus = DFU_OPSTS_ERRUN;
491 length = dfu_rd(block_num, pBuff, length);
492 break;
493 }
494
495 return length;
496 }
497
498 /* USB DFU init via ROM driver */
499 static ErrorCode_t usb_dfu_init(USBD_HANDLE_T hUsb,
500 USB_INTERFACE_DESCRIPTOR *pIntfDesc,
501 uint32_t *mem_base,
502 uint32_t *mem_size)
503 {
504 USBD_DFU_INIT_PARAM_T dfu_param;
505 ErrorCode_t ret = LPC_OK;
506
507 memset((void *) &dfu_param, 0, sizeof(USBD_DFU_INIT_PARAM_T));
508 dfu_param.mem_base = *mem_base;
509 dfu_param.mem_size = *mem_size;
510 /* DFU paramas */
511 dfu_param.wTransferSize = USB_DFU_XFER_SIZE;
512
513 if ((pIntfDesc == 0) ||
514 (pIntfDesc->bInterfaceClass != USB_DEVICE_CLASS_APP) ||
515 (pIntfDesc->bInterfaceSubClass != USB_DFU_SUBCLASS) ) {
516 return ERR_FAILED;
517 }
518
519 dfu_param.intf_desc = (uint8_t *) pIntfDesc;
520 /* user defined functions */
521 dfu_param.DFU_Write = dfu_wr; /* From host */
522 dfu_param.DFU_Read = dfu_rd;/* To host */
523 dfu_param.DFU_Done = dfu_done;
524 dfu_param.DFU_Detach = dfu_detach;
525
526 ret = USBD_API->dfu->init(hUsb, &dfu_param, DFU_STATE_dfuIDLE);
527 /* update memory variables */
528 *mem_base = dfu_param.mem_base;
529 *mem_size = dfu_param.mem_size;
530
531 return ret;
532 }
533
534 /* Sets up USB for DFU operation using boot ROM */
535 static uint32_t algo_dfu_setup(void)
536 {
537 USBD_API_INIT_PARAM_T usb_param;
538 USB_CORE_DESCS_T desc;
539 ErrorCode_t ret;
540 USB_INTERFACE_DESCRIPTOR *pIntfDesc;
541
542 /* Initilize call back structures */
543 memset((void *) &usb_param, 0, sizeof(USBD_API_INIT_PARAM_T));
544
545 /* USB_EPWR power saving mode will be enabled if the boot ROM
546 was booted from USB1 */
547 if ((LPC_SCU->SFSUSB & (1 << 4)) == 0) {
548 usb_param.usb_reg_base = LPC_USB0_BASE;
549 }
550 else {
551 usb_param.usb_reg_base = LPC_USB1_BASE;
552 }
553
554 usb_param.max_num_ep = 6;
555 usb_param.mem_base = 0x20000000;
556 usb_param.mem_size = USBROMBUFFSIZE;
557
558 /* Set the USB descriptors */
559 desc.device_desc = USB_DeviceDescriptor;
560 desc.string_desc = USB_StringDescriptor;
561 desc.full_speed_desc = USB_FsConfigDescriptor;
562 desc.high_speed_desc = USB_HsConfigDescriptor;
563 desc.device_qualifier = USB_DeviceQualifier;
564
565 /* USB Initialization */
566 ret = USBD_API->hw->Init(&hUsb, &desc, &usb_param);
567 if (ret == LPC_OK) {
568 pIntfDesc = (USB_INTERFACE_DESCRIPTOR *) ((uint32_t) desc.high_speed_desc + USB_CONFIGUARTION_DESC_SIZE);
569 ret = usb_dfu_init(hUsb, pIntfDesc, &usb_param.mem_base, &usb_param.mem_size);
570 if (ret != LPC_OK) {
571 return 0;
572 }
573
574 NVIC_EnableIRQ(USB0_IRQn);
575 NVIC_EnableIRQ(USB1_IRQn);
576 }
577
578 USBD_API->hw->Connect(hUsb, 1);
579
580 return 1;
581 }
582
583 /* Reset chip via the RGU */
584 static void lpc18xx43xx_sys_reset(void)
585 {
586 /* Reset core via RGU */
587 while (1) {
588 Chip_RGU_TriggerReset(RGU_CORE_RST);
589 }
590 }
591
596 static void usbPllSetup(void)
597 {
598 /* Nothing to do here, the PLL settings are inherited from the
599 boot ROM on USB boot */
600 }
601
602 /* DFU processing entry point */
603 static void dfu_util_process(void)
604 {
605 PFV pfunc;
606 int i, blks;
607
608 /* Initialize programming interfaces and get device gemometry */
609 dfuprog_regions = algo_flash_init();
610
611 /* Show regions */
612 sprintf(tmpStr, "Number of memory regions : %d\n", dfuprog_regions->num_regions);
613 usbDebug(tmpStr);
614 for (i = 0; i < dfuprog_regions->num_regions; i++) {
615 sprintf(tmpStr, "Region #%d @ 0x%p, size %p bytes\n", i,
616 (void *) dfuprog_regions->pregions[i].region_addr,
617 (void *) dfuprog_regions->pregions[i].region_size);
618 usbDebug(tmpStr);
619 }
620
621 /* Before starting USB, setup USB state for configuration */
622 currStatus = DFU_OPSTS_IDLE;
623
624 /* Setup DFU USB mode and enumerate */
625 if (algo_dfu_setup() == 0) {
626 /* DFU failed, so status can't be returned. Attempt a reset */
627 USBD_API->hw->Connect(hUsb, 0);
628 currStatus = DFU_OPSTS_ERRUN;
629 tickDelayMS(500);
630 }
631
632 /* Processing loop for background programming operation */
633 while (1) {
634 /* Background processing loop */
635 switch (currStatus) {
636 case DFU_OPSTS_IDLE:
637 /* Do nothing when idle */
638 case DFU_OPSTS_ERRER:
639 case DFU_OPSTS_READER:
640 case DFU_OPSTS_PROGER:
641 case DFU_OPSTS_ERRUN:
642 /* Error states are handled in the interrupt handler, so
643 there is nothing to do here. */
644 case DFU_OPSTS_READREADY:
645 case DFU_OPSTS_READTRIG:
646 __WFI();
647 break;
648
649 case DFU_OPSTS_READBUSY:
650 blks = currCmdSize;
651 if (blks > dfuprog_regions->buffer_size) {
652 blks = dfuprog_regions->buffer_size;
653 }
654 if (dfuprog_regions->pprogalgos->read(dfuProgBuff, currCmdAddr,
655 blks) == 0) {
656 currStatus = DFU_OPSTS_READER;
657 }
658 else {
659 /* Read data and return to ready state on completion */
660 currStatus = DFU_OPSTS_READTRIG;
661 currCmdAddr += blks;
662 }
663 break;
664
665 case DFU_OPSTS_ERASE_ALL_ST:
666 /* Starting a full erase operation */
667 currStatus = DFU_OPSTS_ERASE;
668 if (dfuprog_regions->pprogalgos->erase_all() == 0) {
669 currStatus = DFU_OPSTS_ERRER;
670 }
671 break;
672
673 case DFU_OPSTS_ERASE_ST:
674 /* Starting a region erase operation */
675 currStatus = DFU_OPSTS_ERASE;
676 if (dfuprog_regions->pprogalgos->erase_region(currCmdAddr,
677 currCmdSize) == 0) {
678 currStatus = DFU_OPSTS_ERRER;
679 }
680 break;
681
682 case DFU_OPSTS_ERASE:
683 /* Since the erase function is blocking, this state indicatea a
684 successful erase or program operation. Switch back to idle state. */
685 currStatus = DFU_OPSTS_IDLE;
686 break;
687
688 case DFU_OPSTS_PROG_STREAM:
689 /* Nothing to do in this state */
690 __WFI();
691 break;
692
693 case DFU_OPSTS_PROG:
694 if (progSize == 0) {
695 /* Done, go back to idle */
696 currStatus = DFU_OPSTS_IDLE;
697 }
698 else {
699 if (dfuprog_regions->pprogalgos->write((void *) dfuProgBuff,
700 currCmdAddr, progSize) != progSize) {
701 currStatus = DFU_OPSTS_PROGER;
702 }
703 else if ((progSize < dfuprog_regions->buffer_size) ||
704 (currCmdSize == 0)) {
705 currStatus = DFU_OPSTS_IDLE;
706 }
707 else {
708 currStatus = DFU_OPSTS_PROG_STREAM;
709 currCmdAddr += progSize;
710 }
711 }
712 break;
713
714 case DFU_OPSTS_RESET:
715 /* Reset the chip */
716 tickDelayMS(100);
717 USBD_API->hw->Connect(hUsb, 0);
718 NVIC_DisableIRQ(SysTick_IRQn);
719 lpc18xx43xx_sys_reset();
720 break;
721
722 case DFU_OPSTS_EXEC:
723 /* Jump to a address */
724 tickDelayMS(100);
725 pfunc = (PFV) currCmdAddr;
726 USBD_API->hw->Connect(hUsb, 0);
727 NVIC_DisableIRQ(SysTick_IRQn);
728 pfunc();
729 break;
730
731 case DFU_OPSTS_LOOP:
732 /* Dead loop, happens on an error */
733 USBD_API->hw->Connect(hUsb, 0);
734 while (1) {}
735 }
736 }
737 }
738
739 /*****************************************************************************
740 * Public functions
741 ****************************************************************************/
742
747 void SysTick_Handler(void)
748 {
749 if (u32Milliseconds > 0) {
750 u32Milliseconds--;
751 }
752 }
753
754 /* Queues a message for DFU status transfer */
755 void usbDebug(char *tmp)
756 {
757 if (verifyDebug == true) {
758 /* Wrap without limits */
759 while (*tmp != '\0') {
760 usbBuff[usbStrIn] = *tmp;
761 usbStrIn++;
762 if (usbStrIn >= USBMSGBUFFSIZE) {
763 usbStrIn = 0;
764 }
765 tmp++;
766 }
767 }
768 }
769
774 int main(void)
775 {
776 /* Updates SystemCoreClock global var with current clock speed */
777 SystemCoreClockUpdate();
778
779 /* Setup and enable USB PLL and PHY */
780 usbPllSetup();
781
782 /* Setup 1mS tick source for timing */
783 SysTick_Config(Chip_Clock_GetRate(CLK_MX_MXCORE) / 1000);
784
785 /* Start debug output buffering for for DFU Utility */
786 usbDebugSetup();
787 usbDebug("LPC18xx/43xx DFUSec programming API tool\n");
788 usbDebug("Build date: " __DATE__ ":" __TIME__ "\n");
789
790 /* Will stay in processing until a reset is requested by host */
791 dfu_util_process();
792
793 /* dfu_util_process() shouldn't exit, so reset the chip/board
794 if it does. */
795 lpc18xx43xx_sys_reset();
796
797 return 0;
798 }