00001
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050 #include "conf_usb.h"
00051
00052
00053 #if USB_DEVICE_FEATURE == ENABLED
00054
00055 #include <avr32/io.h>
00056 #include <stddef.h>
00057 #include <string.h>
00058 #include "compiler.h"
00059 #include "pm.h"
00060
00061 #include "flashc.h"
00062 #include "usb_drv.h"
00063 #include "usb_task.h"
00064 #include "usb_descriptors.h"
00065 #include "usb_dfu.h"
00066 #include "boot.h"
00067 #include "conf_isp.h"
00068 #include "isp.h"
00069
00070
00071
00072
00079 #if LITTLE_ENDIAN_MCU
00080 #define Dfu_format_mcu_to_dfu_data(width, data) (TPASTE2(Swap, width)(data))
00081 #define Dfu_format_dfu_to_mcu_data(width, data) (TPASTE2(Swap, width)(data))
00082 #define dfu_format_mcu_to_dfu_data(width, data) (TPASTE2(swap, width)(data))
00083 #define dfu_format_dfu_to_mcu_data(width, data) (TPASTE2(swap, width)(data))
00084 #else // BIG_ENDIAN_MCU
00085 #define Dfu_format_mcu_to_dfu_data(width, data) ((TPASTE2(U, width))(data))
00086 #define Dfu_format_dfu_to_mcu_data(width, data) ((TPASTE2(U, width))(data))
00087 #define dfu_format_mcu_to_dfu_data(width, data) ((TPASTE2(U, width))(data))
00088 #define dfu_format_dfu_to_mcu_data(width, data) ((TPASTE2(U, width))(data))
00089 #endif
00091
00092
00093
00094 #define CMD_GRP_DNLOAD 0x01
00095 #define CMD_GRP_UPLOAD 0x03
00096 #define CMD_GRP_EXEC 0x04
00097 #define CMD_GRP_SELECT 0x06
00098
00099
00100 #define CMD_PROGRAM_START 0x00
00101
00102
00103 #define CMD_READ_MEMORY 0x00
00104 #define CMD_BLANK_CHECK 0x01
00105
00106
00107 #define CMD_ERASE 0x00
00108 #define CMD_START_APPLI 0x03
00109
00110
00111 #define CMD_SELECT_MEMORY 0x03
00112
00113
00114 #define CMD_ERASE_ARG_CHIP 0xFF
00115
00116
00117 #define CMD_START_APPLI_ARG_RESET 0x00
00118 #define CMD_START_APPLI_ARG_NO_RESET 0x01
00119
00120
00121 #define CMD_SELECT_MEMORY_ARG_UNIT 0x00
00122 #define CMD_SELECT_MEMORY_ARG_PAGE 0x01
00123
00124
00125 #define MEM_FLASH 0x00
00126 #define MEM_EEPROM 0x01
00127 #define MEM_SECURITY 0x02
00128 #define MEM_CONFIGURATION 0x03
00129 #define MEM_BOOTLOADER 0x04
00130 #define MEM_SIGNATURE 0x05
00131 #define MEM_USER 0x06
00132
00133
00134 #define MEM_COUNT (MEM_USER + 1)
00135
00136
00137 #define PRODUCT_MANUFACTURER_ID_ADDRESS 0x00
00138 #define PRODUCT_FAMILY_ID_ADDRESS 0x01
00139 #define PRODUCT_ID_ADDRESS 0x02
00140 #define PRODUCT_REVISION_ADDRESS 0x03
00141
00142
00143 #define PRODUCT_INF_ITEM_COUNT (PRODUCT_REVISION_ADDRESS + 1)
00144
00145
00146 #define ISP_VERSION_ADDRESS 0x00
00147 #define ISP_ID0_ADDRESS 0x01
00148 #define ISP_ID1_ADDRESS 0x02
00149
00150
00151 #define ISP_INF_ITEM_COUNT (ISP_ID1_ADDRESS + 1)
00152
00153
00154
00155
00156 static void mem_flash_read(void *dst, U32 src, size_t nbytes);
00157 static void mem_flash_write(U32 dst, const void *src, size_t nbytes);
00158 static void mem_security_read(void *dst, U32 src, size_t nbytes);
00159 static void mem_security_write(U32 dst, const void *src, size_t nbytes);
00160 static void mem_configuration_read(void *dst, U32 src, size_t nbytes);
00161 static void mem_configuration_write(U32 dst, const void *src, size_t nbytes);
00162 static void mem_bootloader_read(void *dst, U32 src, size_t nbytes);
00163 static void mem_signature_read(void *dst, U32 src, size_t nbytes);
00164 static void mem_user_read(void *dst, U32 src, size_t nbytes);
00165 static void mem_user_write(U32 dst, const void *src, size_t nbytes);
00166
00167
00168
00169
00170 typedef union
00171 {
00172 U32 long_address;
00173 struct
00174 {
00175 unsigned int page : 16;
00176 unsigned int page_offset : 16;
00177 };
00178 } address_t;
00179
00180
00181 static U8 PRODUCT_INF[PRODUCT_INF_ITEM_COUNT] =
00182 {
00183 PRODUCT_MANUFACTURER_ID,
00184 PRODUCT_FAMILY_ID
00185 };
00186
00187 static const U8 ISP_INF[ISP_INF_ITEM_COUNT] =
00188 {
00189 ISP_VERSION,
00190 ISP_ID0,
00191 ISP_ID1
00192 };
00193
00194 static address_t MEMORY_END_ADDRESS[MEM_COUNT] =
00195 {
00196
00197 #if (defined __GNUC__) && ((defined __AVR32_UC3B0512__) || \
00198 (defined __AVR32_UC3B1512__)) || \
00199 (defined __ICCAVR32__) && ((defined __AT32UC3B0512__) || \
00200 (defined __AT32UC3B1512__))
00201 #undef AVR32_FLASH_SIZE
00202 #define AVR32_FLASH_SIZE 0x00080000
00203 #endif
00204
00205
00206 {AVR32_FLASH_SIZE - 1},
00207
00208
00209 {0},
00210
00211
00212 {0},
00213
00214
00215 {AVR32_FLASHC_GPF_NUM - 1},
00216
00217
00218 {sizeof(ISP_INF) - 1},
00219
00220
00221 {sizeof(PRODUCT_INF) - 1},
00222
00223
00224 {AVR32_FLASHC_USER_PAGE_SIZE - 1}
00225 };
00226
00227 static const struct
00228 {
00229 void (*read)(void *dst, U32 src, size_t nbytes);
00230 void (*write)(U32 dst, const void *src, size_t nbytes);
00231 } MEMORY_ACCESS[MEM_COUNT] =
00232 {
00233
00234 {
00235 mem_flash_read,
00236 mem_flash_write
00237 },
00238
00239
00240 {
00241 NULL,
00242 NULL
00243 },
00244
00245
00246 {
00247 mem_security_read,
00248 mem_security_write
00249 },
00250
00251
00252 {
00253 mem_configuration_read,
00254 mem_configuration_write
00255 },
00256
00257
00258 {
00259 mem_bootloader_read,
00260 NULL
00261 },
00262
00263
00264 {
00265 mem_signature_read,
00266 NULL
00267 },
00268
00269
00270 {
00271 mem_user_read,
00272 mem_user_write
00273 }
00274 };
00275
00276 static const U8 MEMORY_ERASE_VALUE[MEM_COUNT] =
00277 {
00278
00279 0xFF,
00280
00281
00282 0xFF,
00283
00284
00285 0x00,
00286
00287
00288 0x01,
00289
00290
00291 0x00,
00292
00293
00294 0x00,
00295
00296
00297 0xFF
00298 };
00299
00300 static Bool security_active = TRUE;
00301 static S32 length;
00302 static U8 cmd_group = CMD_GRP_EXEC;
00303 static U8 cmd = CMD_START_APPLI;
00304 static U8 memory = MEM_FLASH;
00305 static address_t start_address;
00306 static address_t end_address;
00307 static U32 data_bytes;
00308 static U8 dfu_frame[DFU_FRAME_LENGTH];
00309 static U8 dfu_status = STATUS_OK;
00310
00311 U8 usb_dfu_status = STATUS_OK;
00312 U8 usb_dfu_state = STATE_dfuIDLE;
00313
00314
00320 static void write_word_to_user_page(int offset, U32 value)
00321 {
00322 int i;
00323 Union32 flash_word;
00324 volatile U32 *pu32_flash_ptr = (U32 *)AVR32_FLASHC_USER_PAGE_ADDRESS;
00325
00326
00327 flashc_clear_page_buffer();
00328
00329
00330
00331
00332 for(i = 0; i < AVR32_FLASHC_USER_PAGE_SIZE; i += sizeof(U32))
00333 {
00334 flash_word.u32 = *pu32_flash_ptr;
00335 if(i == offset)
00336 flash_word.u32 = value;
00337 *pu32_flash_ptr++ = flash_word.u32;
00338 }
00339
00340
00341 flashc_erase_user_page(FALSE);
00342
00343
00344 flashc_write_user_page();
00345 }
00346
00347
00357 #define POLYNOMIAL (ISP_CFG1_CRC8_POLYNOMIAL << 7)
00358 static U8 Crc8( U8 inCrc, U8 inData )
00359 {
00360 int i;
00361 U16 data;
00362
00363 data = inCrc ^ inData;
00364 data <<= 8;
00365
00366 for ( i = 0; i < 8; i++ )
00367 {
00368 if (( data & 0x8000 ) != 0 )
00369 {
00370 data = data ^ POLYNOMIAL;
00371 }
00372 data = data << 1;
00373 }
00374 return (unsigned char)( data >> 8 );
00375 }
00376
00377 static Bool is_isp_forced(void)
00378 {
00379 return((ISP_CFG1&ISP_CFG1_FORCE_MASK)>>ISP_CFG1_FORCE_OFFSET);
00380 }
00381
00382 static void force_isp(Bool force)
00383 {
00384 U32 u32_tempo;
00385 U8 crc8 = 0;
00386 int i;
00387
00388
00389
00390 u32_tempo = (ISP_CFG1 & ~ISP_CFG1_FORCE_MASK) | ((force<<ISP_CFG1_FORCE_OFFSET) & ISP_CFG1_FORCE_MASK);
00391
00392
00393 for(i=24; i; i-=8)
00394 crc8 = Crc8(crc8, u32_tempo>>i);
00395 u32_tempo = (u32_tempo & ~ISP_CFG1_CRC8_MASK) | ((crc8<<ISP_CFG1_CRC8_OFFSET) & ISP_CFG1_CRC8_MASK);
00396
00397
00398 write_word_to_user_page(ISP_CFG1_OFFSET, u32_tempo);
00399 }
00400
00401
00402 static Bool get_and_check_mem_range(void)
00403 {
00404 start_address.page_offset = Usb_read_endpoint_data(EP_CONTROL, 16);
00405 start_address.page_offset = dfu_format_dfu_to_mcu_data(16, start_address.page_offset);
00406 end_address.page_offset = Usb_read_endpoint_data(EP_CONTROL, 16);
00407 end_address.page_offset = dfu_format_dfu_to_mcu_data(16, end_address.page_offset);
00408
00409 if (end_address.long_address < start_address.long_address ||
00410 end_address.long_address > MEMORY_END_ADDRESS[memory].long_address)
00411 {
00412 dfu_status = STATUS_errADDRESS;
00413 return FALSE;
00414 }
00415
00416 data_bytes = end_address.long_address - start_address.long_address + 1;
00417 return TRUE;
00418 }
00419
00420
00421 static void mem_flash_read(void *dst, U32 src, size_t nbytes)
00422 {
00423 memcpy(dst, AVR32_FLASH + src, nbytes);
00424 }
00425
00426
00427 static void mem_flash_write(U32 dst, const void *src, size_t nbytes)
00428 {
00429 flashc_memcpy(AVR32_FLASH + dst, src, nbytes, FALSE);
00430 }
00431
00432
00433 static void mem_security_read(void *dst, U32 src, size_t nbytes)
00434 {
00435 if (nbytes)
00436 *(U8 *)dst = flashc_is_security_bit_active();
00437 }
00438
00439
00440 static void mem_security_write(U32 dst, const void *src, size_t nbytes)
00441 {
00442 if (nbytes && *(U8 *)src)
00443 {
00444 security_active = TRUE;
00445 flashc_activate_security_bit();
00446 }
00447 }
00448
00449
00450 static void mem_configuration_read(void *dst, U32 src, size_t nbytes)
00451 {
00452 U8 *dest = dst;
00453 while (nbytes--)
00454 *dest++ = flashc_read_gp_fuse_bit(src++);
00455 }
00456
00457
00458 static void mem_configuration_write(U32 dst, const void *src, size_t nbytes)
00459 {
00460 const U8 *source = src;
00461 while (nbytes--)
00462 flashc_set_gp_fuse_bit(dst++, *source++);
00463 }
00464
00465
00466 static void mem_bootloader_read(void *dst, U32 src, size_t nbytes)
00467 {
00468 memcpy(dst, ISP_INF + src, nbytes);
00469 }
00470
00471
00472 static void mem_signature_read(void *dst, U32 src, size_t nbytes)
00473 {
00474 memcpy(dst, PRODUCT_INF + src, nbytes);
00475 }
00476
00477
00478 static void mem_user_read(void *dst, U32 src, size_t nbytes)
00479 {
00480 memcpy(dst, (U8 *)AVR32_FLASHC_USER_PAGE + src, nbytes);
00481 }
00482
00483
00484 static void mem_user_write(U32 dst, const void *src, size_t nbytes)
00485 {
00486 flashc_memcpy(AVR32_FLASHC_USER_PAGE + dst, src, nbytes, TRUE);
00487 }
00488
00489
00490 static void erase_check_mem(void)
00491 {
00492 U8 *frame;
00493 U32 frame_bytes;
00494
00495 while (data_bytes)
00496 {
00497 frame = dfu_frame;
00498 frame_bytes = min(data_bytes, DFU_FRAME_LENGTH);
00499 data_bytes -= frame_bytes;
00500
00501 MEMORY_ACCESS[memory].read(frame, start_address.long_address, frame_bytes);
00502
00503 while (frame_bytes--)
00504 {
00505 if (*frame++ != MEMORY_ERASE_VALUE[memory])
00506 {
00507 dfu_status = STATUS_errCHECK_ERASED;
00508 return;
00509 }
00510 start_address.long_address++;
00511 }
00512 }
00513 }
00514
00515
00516 static void read_mem(void)
00517 {
00518 void *frame;
00519 U32 frame_bytes;
00520
00521 while (data_bytes)
00522 {
00523 frame = dfu_frame;
00524 frame_bytes = min(data_bytes, DFU_FRAME_LENGTH);
00525 data_bytes -= frame_bytes;
00526
00527 MEMORY_ACCESS[memory].read(frame, start_address.long_address, frame_bytes);
00528 start_address.long_address += frame_bytes;
00529
00530 while (frame_bytes)
00531 {
00532 while (!Is_usb_control_in_ready());
00533
00534 Usb_reset_endpoint_fifo_access(EP_CONTROL);
00535 frame_bytes = usb_write_ep_txpacket(EP_CONTROL, frame, frame_bytes, (const void **)&frame);
00536 Usb_ack_control_in_ready_send();
00537 }
00538 }
00539 }
00540
00541
00542 static void write_mem(void)
00543 {
00544 void *frame;
00545 U32 frame_bytes, unaligned_frame_bytes;
00546
00547 data_bytes += Get_align(start_address.long_address, EP_CONTROL_LENGTH);
00548 length -= EP_CONTROL_LENGTH + Align_up(data_bytes, EP_CONTROL_LENGTH);
00549
00550 while (data_bytes)
00551 {
00552 frame = dfu_frame;
00553 frame_bytes = min(data_bytes, DFU_FRAME_LENGTH);
00554 unaligned_frame_bytes = frame_bytes - Get_align(start_address.long_address, EP_CONTROL_LENGTH);
00555 data_bytes -= frame_bytes;
00556
00557 while (frame_bytes)
00558 {
00559 while (!Is_usb_control_out_received());
00560
00561 Usb_reset_endpoint_fifo_access(EP_CONTROL);
00562 frame_bytes = usb_read_ep_rxpacket(EP_CONTROL, frame, frame_bytes, &frame);
00563 Usb_ack_control_out_received_free();
00564 }
00565
00566 MEMORY_ACCESS[memory].write(start_address.long_address,
00567 dfu_frame + Get_align(start_address.long_address, EP_CONTROL_LENGTH),
00568 unaligned_frame_bytes);
00569 start_address.long_address += unaligned_frame_bytes;
00570 }
00571
00572 while (length > 0)
00573 {
00574 while (!Is_usb_control_out_received());
00575 Usb_ack_control_out_received_free();
00576 length -= EP_CONTROL_LENGTH;
00577 }
00578 }
00579
00580
00581 void usb_dfu_init(void)
00582 {
00583 PRODUCT_INF[PRODUCT_ID_ADDRESS] =
00584 Rd_bitfield(Get_system_register(AVR32_CONFIG0), AVR32_CONFIG0_PROCESSORID_MASK);
00585 PRODUCT_INF[PRODUCT_REVISION_ADDRESS] =
00586 Rd_bitfield(Get_system_register(AVR32_CONFIG0), AVR32_CONFIG0_PROCESSORREVISION_MASK);
00587
00588 MEMORY_END_ADDRESS[MEM_FLASH].long_address = flashc_get_flash_size() - 1;
00589
00590 security_active = flashc_is_security_bit_active();
00591 }
00592
00593
00594 static void usb_dfu_stop(void)
00595 {
00596 force_isp(FALSE);
00597
00598 Usb_ack_control_out_received_free();
00599 Usb_ack_control_in_ready_send();
00600
00601 while (!Is_usb_setup_received());
00602 Usb_ack_setup_received_free();
00603 Usb_ack_control_in_ready_send();
00604
00605 while (!Is_usb_control_in_ready());
00606
00607 Disable_global_interrupt();
00608 Usb_disable();
00609 (void)Is_usb_enabled();
00610 Enable_global_interrupt();
00611 Usb_disable_otg_pad();
00612 }
00613
00614
00617 Bool usb_dfu_dnload(void)
00618 {
00619 static U8 tmp_memory;
00620 static U16 tmp_page;
00621
00622 if (!is_isp_forced()) force_isp(TRUE);
00623
00624 dfu_status = STATUS_OK;
00625
00626 Usb_read_endpoint_data(EP_CONTROL, 16);
00627 Usb_read_endpoint_data(EP_CONTROL, 16);
00628 length = Usb_read_endpoint_data(EP_CONTROL, 16);
00629 length = usb_format_usb_to_mcu_data(16, length);
00630 Usb_ack_setup_received_free();
00631
00632 if (length)
00633 {
00634 while (!Is_usb_control_out_received());
00635 Usb_reset_endpoint_fifo_access(EP_CONTROL);
00636
00637 cmd_group = Usb_read_endpoint_data(EP_CONTROL, 8);
00638 cmd = Usb_read_endpoint_data(EP_CONTROL, 8);
00639 switch (cmd_group)
00640 {
00641 case CMD_GRP_DNLOAD:
00642 if (security_active)
00643 {
00644 goto unsupported_request;
00645 }
00646 if (!get_and_check_mem_range()) break;
00647 if (!MEMORY_ACCESS[memory].write)
00648 {
00649 dfu_status = STATUS_errWRITE;
00650 break;
00651 }
00652 switch (cmd)
00653 {
00654 case CMD_PROGRAM_START:
00655 Usb_ack_control_out_received_free();
00656 write_mem();
00657 break;
00658
00659 default:
00660 goto unsupported_request;
00661 }
00662 break;
00663
00664 case CMD_GRP_UPLOAD:
00665 if (security_active)
00666 {
00667 goto unsupported_request;
00668 }
00669 if (!get_and_check_mem_range()) break;
00670 if (!MEMORY_ACCESS[memory].read)
00671 {
00672 dfu_status = STATUS_errVERIFY;
00673 break;
00674 }
00675 switch (cmd)
00676 {
00677 case CMD_READ_MEMORY:
00678 break;
00679
00680 case CMD_BLANK_CHECK:
00681 erase_check_mem();
00682 break;
00683
00684 default:
00685 goto unsupported_request;
00686 }
00687 break;
00688
00689 case CMD_GRP_EXEC:
00690 switch (cmd)
00691 {
00692 case CMD_ERASE:
00693 switch (Usb_read_endpoint_data(EP_CONTROL, 8))
00694 {
00695 case CMD_ERASE_ARG_CHIP:
00696 memory = MEM_FLASH;
00697 end_address.long_address = start_address.long_address = 0;
00698 flashc_lock_all_regions(FALSE);
00699 flashc_erase_all_pages(FALSE);
00700 security_active = FALSE;
00701 break;
00702
00703 default:
00704 goto unsupported_request;
00705 }
00706 break;
00707
00708 case CMD_START_APPLI:
00709 switch (Usb_read_endpoint_data(EP_CONTROL, 8))
00710 {
00711 case CMD_START_APPLI_ARG_RESET:
00712 usb_dfu_stop();
00713 Disable_global_interrupt();
00714 AVR32_WDT.ctrl = AVR32_WDT_CTRL_EN_MASK |
00715 (10 << AVR32_WDT_CTRL_PSEL_OFFSET) |
00716 (AVR32_WDT_KEY_VALUE << AVR32_WDT_CTRL_KEY_OFFSET);
00717 AVR32_WDT.ctrl = AVR32_WDT_CTRL_EN_MASK |
00718 (10 << AVR32_WDT_CTRL_PSEL_OFFSET) |
00719 ((~AVR32_WDT_KEY_VALUE << AVR32_WDT_CTRL_KEY_OFFSET) & AVR32_WDT_CTRL_KEY_MASK);
00720 while (1);
00721
00722 case CMD_START_APPLI_ARG_NO_RESET:
00723 usb_dfu_stop();
00724 sys_clk_gen_stop();
00725 wait_10_ms();
00726 boot_program();
00727 break;
00728
00729 default:
00730 goto unsupported_request;
00731 }
00732 break;
00733
00734 default:
00735 goto unsupported_request;
00736 }
00737 break;
00738
00739 case CMD_GRP_SELECT:
00740 if (security_active)
00741 {
00742 goto unsupported_request;
00743 }
00744 switch (cmd)
00745 {
00746 case CMD_SELECT_MEMORY:
00747 switch (Usb_read_endpoint_data(EP_CONTROL, 8))
00748 {
00749 case CMD_SELECT_MEMORY_ARG_UNIT:
00750 switch (tmp_memory = Usb_read_endpoint_data(EP_CONTROL, 8))
00751 {
00752 case MEM_FLASH:
00753 case MEM_EEPROM:
00754 case MEM_SECURITY:
00755 case MEM_CONFIGURATION:
00756 case MEM_BOOTLOADER:
00757 case MEM_SIGNATURE:
00758 case MEM_USER:
00759 memory = tmp_memory;
00760 end_address.long_address = start_address.long_address = 0;
00761 break;
00762
00763 default:
00764 dfu_status = STATUS_errADDRESS;
00765 }
00766 break;
00767
00768 case CMD_SELECT_MEMORY_ARG_PAGE:
00769 MSB(tmp_page) = Usb_read_endpoint_data(EP_CONTROL, 8);
00770 LSB(tmp_page) = Usb_read_endpoint_data(EP_CONTROL, 8);
00771 if (tmp_page <= MEMORY_END_ADDRESS[memory].page)
00772 {
00773 end_address.page = start_address.page = tmp_page;
00774 }
00775 else dfu_status = STATUS_errADDRESS;
00776 break;
00777
00778 default:
00779 goto unsupported_request;
00780 }
00781 break;
00782
00783 default:
00784 goto unsupported_request;
00785 }
00786 break;
00787
00788 default:
00789 unsupported_request:
00790 dfu_status = STATUS_errSTALLEDPKT;
00791 }
00792
00793 Usb_ack_control_out_received_free();
00794 }
00795
00796 usb_dfu_status = dfu_status;
00797 if (usb_dfu_status != STATUS_OK &&
00798 usb_dfu_status != STATUS_errCHECK_ERASED) return FALSE;
00799
00800 Usb_ack_control_in_ready_send();
00801 while (!Is_usb_control_in_ready());
00802 return TRUE;
00803 }
00804
00805
00808 Bool usb_dfu_upload(void)
00809 {
00810 Usb_ack_setup_received_free();
00811 Usb_reset_endpoint_fifo_access(EP_CONTROL);
00812
00813 if (cmd_group == CMD_GRP_UPLOAD &&
00814 (dfu_status == STATUS_OK ||
00815 dfu_status == STATUS_errCHECK_ERASED))
00816 {
00817 switch (cmd)
00818 {
00819 case CMD_READ_MEMORY:
00820 read_mem();
00821 break;
00822
00823 case CMD_BLANK_CHECK:
00824 Usb_write_endpoint_data(EP_CONTROL, 16, dfu_format_mcu_to_dfu_data(16, start_address.page_offset));
00825 break;
00826
00827 default:
00828 goto unsupported_request;
00829 }
00830 }
00831 else
00832 {
00833 unsupported_request:
00834 dfu_status = STATUS_errSTALLEDPKT;
00835 }
00836
00837 usb_dfu_status = dfu_status;
00838 if (usb_dfu_status != STATUS_OK &&
00839 usb_dfu_status != STATUS_errCHECK_ERASED) return FALSE;
00840
00841 if (Usb_byte_count(EP_CONTROL)) Usb_ack_control_in_ready_send();
00842 while (!Is_usb_control_out_received());
00843 Usb_ack_control_out_received_free();
00844 return TRUE;
00845 }
00846
00847
00848 #endif // USB_DEVICE_FEATURE == ENABLED