├── .gitignore
├── msc_disk.h
├── FileOnPIco
├── INFO_UF2.TXT
└── INDEX.HTM
├── fatImages
├── PicoImage.7z
├── TinyUSBFat12.img
└── README.md
├── uploads
├── hello_uart.bin
└── hello_uart.uf2
├── checkUF2.h
├── LICENSE.TXT
├── CMakeLists.txt
├── Fat16Struct.h
├── README.md
├── main.c
├── tusb_config.h
├── fat12.h
├── usb_descriptors.c
└── msc_disk.c
/.gitignore:
--------------------------------------------------------------------------------
1 | build/
2 | PicoImage.img
--------------------------------------------------------------------------------
/msc_disk.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | void printReserveSectFat();
--------------------------------------------------------------------------------
/FileOnPIco/INFO_UF2.TXT:
--------------------------------------------------------------------------------
1 | UF2 Bootloader v3.0
2 | Model: Raspberry Pi RP2
3 | Board-ID: RPI-RP2
4 |
--------------------------------------------------------------------------------
/fatImages/PicoImage.7z:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brendena/pico_drag_n_drop_programmer/HEAD/fatImages/PicoImage.7z
--------------------------------------------------------------------------------
/uploads/hello_uart.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brendena/pico_drag_n_drop_programmer/HEAD/uploads/hello_uart.bin
--------------------------------------------------------------------------------
/uploads/hello_uart.uf2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brendena/pico_drag_n_drop_programmer/HEAD/uploads/hello_uart.uf2
--------------------------------------------------------------------------------
/fatImages/TinyUSBFat12.img:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brendena/pico_drag_n_drop_programmer/HEAD/fatImages/TinyUSBFat12.img
--------------------------------------------------------------------------------
/fatImages/README.md:
--------------------------------------------------------------------------------
1 | if you want to see the PicoImage.img you need uncompress the PicoImage.7z. Github wouldn't let me push up such a large file.
--------------------------------------------------------------------------------
/FileOnPIco/INDEX.HTM:
--------------------------------------------------------------------------------
1 |
Redirecting to raspberrypi.com
--------------------------------------------------------------------------------
/checkUF2.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | //return size UF2
4 | unsigned char * getUF2Info(unsigned char * buffer,
5 | unsigned int * returnSize)
6 | {
7 | unsigned char * returnBuff = 0;
8 | unsigned int * intBuff = (unsigned int*)buffer;
9 | //printf("first number 0x%x, 0x%x, 0x%x\n",intBuff[0],intBuff[1], intBuff[142]);
10 | if(intBuff[0] == 0x0A324655 &&
11 | intBuff[1] == 0x9E5D5157 &&
12 | intBuff[127] == 0x0AB16F30)
13 | {
14 | printf("flags %x\n", intBuff[2]);
15 | printf("return size %x\n", intBuff[4]);
16 | *returnSize = intBuff[4];
17 | returnBuff = (unsigned char *)&buffer[32];
18 | }
19 |
20 | return returnBuff;
21 | }
--------------------------------------------------------------------------------
/LICENSE.TXT:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2018, hathach (tinyusb.org)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.13)
2 |
3 | include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake)
4 | include($ENV{PICO_SDK_PATH}/tools/CMakeLists.txt)
5 |
6 |
7 |
8 | project(PICO_MSC C CXX ASM)
9 |
10 | set(CMAKE_C_STANDARD 11)
11 | set(CMAKE_CXX_STANDARD 17)
12 |
13 |
14 | pico_sdk_init()
15 |
16 | add_executable(PICO_MSC)
17 |
18 | target_sources(PICO_MSC PUBLIC
19 | ${CMAKE_CURRENT_LIST_DIR}/main.c
20 | ${CMAKE_CURRENT_LIST_DIR}/usb_descriptors.c
21 | ${CMAKE_CURRENT_LIST_DIR}/msc_disk.c
22 | )
23 |
24 | # Make sure TinyUSB can find tusb_config.h
25 | target_include_directories(PICO_MSC PUBLIC
26 | ${CMAKE_CURRENT_LIST_DIR})
27 |
28 | # In addition to pico_stdlib required for common PicoSDK functionality, add dependency on tinyusb_device
29 | # for TinyUSB device support and tinyusb_board for the additional board support library used by the example
30 | target_link_libraries(PICO_MSC PUBLIC pico_stdlib tinyusb_device tinyusb_board hardware_flash)
31 |
32 | # Uncomment this line to enable fix for Errata RP2040-E5 (the fix requires use of GPIO 15)
33 | #target_compile_definitions(PICO_MSC PUBLIC PICO_RP2040_USB_DEVICE_ENUMERATION_FIX=1)
34 |
35 | pico_add_extra_outputs(PICO_MSC)
36 |
37 | pico_enable_stdio_usb(PICO_MSC 0)
38 | pico_enable_stdio_uart(PICO_MSC 1)
39 |
40 |
41 | set(PICO_COPY_TO_RAM,1)
42 | #add_compile_definitions(PICO_COPY_TO_RAM=1)
43 | #add_definitions(-DPICO_COPY_TO_RAM=1)
--------------------------------------------------------------------------------
/Fat16Struct.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "assert.h"
4 | #include "stdio.h"
5 | #include "stdint.h"
6 |
7 | typedef struct {
8 | char name[8];
9 | char ext[3];
10 | uint8_t attrs;
11 | uint8_t reserved;
12 | uint8_t createTimeFine;
13 | uint16_t createTime;
14 | uint16_t createDate;
15 | uint16_t lastAccessDate;
16 | uint16_t highStartCluster;
17 | uint16_t updateTime;
18 | uint16_t updateDate;
19 | uint16_t startCluster;
20 | uint32_t size;
21 |
22 | } __attribute__((packed)) DirEntry;
23 |
24 | static_assert(sizeof(DirEntry) == 32, "DirEntry size is not right");
25 |
26 | typedef struct ReserveSect {
27 | uint8_t bootJump[3]; /* 0 Jump to bootstrap */
28 | uint8_t oemName[8]; /* 3 OEM Manufacturer name */
29 | uint16_t sectorSize __attribute((packed)); /* 11 Sector size in bytes */
30 | uint8_t clusterSize; /* 13 Sectors per cluster */
31 | uint16_t reservedSectors __attribute((packed)); /* 14 Number of reserved sectors */
32 | uint8_t fatCopies; /* 16 # of FAT copies */
33 | uint16_t rootEirEntries __attribute((packed)); /* 17 # of root directory entries */
34 | uint16_t totalSectorsFat16 __attribute((packed)); /* 19 (UNUSED FAT32) Total number of sectors */
35 | uint8_t mediaType; /* 21 Media type */
36 | uint16_t fatTableSize __attribute((packed));
37 | uint16_t secPerTrk __attribute((packed));
38 | uint16_t numHeads __attribute((packed));
39 | uint32_t hiddSec __attribute((packed));
40 | uint32_t totalSec32 __attribute((packed));
41 | } __attribute((packed)) ReserveSect;
42 |
43 |
44 | void printReserveSect(ReserveSect * bootSect)
45 | {
46 | printf("bootOEM %.8s\n", bootSect->oemName);
47 | printf("cluster size %x\n",bootSect->clusterSize);
48 | printf("fat copies %x\n", bootSect->fatCopies);
49 | printf("fat table size %x\n", bootSect->fatTableSize);
50 | printf("totalSec32 %x\n", bootSect->totalSec32);
51 | }
52 |
53 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Example unoptimized Drag n' Drop Programmer
2 | This example is trying to mimic the way that the raspberry pi pico bootloader copies a UF2 file into the flash. The actuall bootloader can be found [here](https://github.com/raspberrypi/pico-bootrom), but it's highly optimized "by design", so i made this to explore how it worked at a less optimized way. Starting point for this was the [tinyUSB CDC_MSC example](https://github.com/hathach/tinyusb/tree/master/examples/device/cdc_msc)
3 |
4 | ## [Video describing project](https://www.youtube.com/watch?v=tmmHijhct_k)
5 |
6 | ## Things inside this demo are
7 | * USB MSC - "USB storage"
8 | * FAT16 file system
9 | * wrighting to flash
10 | * Basic UF2 Parsing
11 |
12 |
13 | ## to build
14 | * cmake .. -DPICO_COPY_TO_RAM=1
15 |
16 | ## Command to flash pico
17 | * openocd -f interface/picoprobe.cfg -f target/rp2040.cfg -c "program PICO_MSC.elf verify reset exit"
18 |
19 | # Things inside this repo
20 |
21 | * fatImages - These are straight rips from a raspberry pi pico. Usefully for see the raw hex values of the fat table
22 | * FileOnPico - These are the files that the pico has by default
23 | * uploads - these are test programs that you can drag onto the raspberry pi pico
24 |
25 |
26 |
27 |
28 | # important links
29 |
30 | ### Fat file system
31 | * [best overview of fat files](http://elm-chan.org/docs/fat_e.html)
32 | * [another good one](https://www.pjrc.com/tech/8051/ide/fat32.html)
33 | * [more fat](http://www.tavi.co.uk/phobos/fat.html#media_descriptor)
34 |
35 | ### Moving program from flash to RAM
36 | * [Raspberry pi forum post about flash to ram](https://forums.raspberrypi.com/viewtopic.php?t=318471)
37 | * [LD_script for copy to ram](https://github.com/raspberrypi/pico-sdk/blob/2062372d203b372849d573f252cf7c6dc2800c0a/src/rp2_common/pico_standard_link/memmap_copy_to_ram.ld)
38 | * [CMAKE section to copy flash to ram](https://github.com/raspberrypi/pico-sdk/blob/2062372d203b372849d573f252cf7c6dc2800c0a/src/rp2_common/pico_standard_link/CMakeLists.txt#L49)
39 |
40 | ### No flash vs copy to ram
41 | * https://forums.raspberrypi.com/viewtopic.php?t=312474
42 |
43 |
44 | ### Wrighting to flash
45 | * https://www.makermatrix.com/blog/read-and-write-data-with-the-pi-pico-onboard-flash/
46 | * https://raspberrypi.github.io/pico-sdk-doxygen/group__hardware__flash.html
47 | * https://kevinboone.me/picoflash.html?i=1
48 |
49 |
50 | ### UF2 File conversion
51 | * [Good wright up on UF2](https://microsoft.github.io/uf2/)
52 |
53 | ### [How to reset the chip](https://raspberrypi.stackexchange.com/questions/132439/pi-pico-software-reset-using-the-c-sdk)
54 |
--------------------------------------------------------------------------------
/main.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #include "bsp/board.h"
6 | #include "tusb.h"
7 | #include
8 | #include "pico/stdlib.h"
9 | #include "pico.h"
10 | #include
11 | //--------------------------------------------------------------------+
12 | // MACRO CONSTANT TYPEDEF PROTYPES
13 | //--------------------------------------------------------------------+
14 |
15 | /* Blink pattern
16 | * - 250 ms : device not mounted
17 | * - 1000 ms : device mounted
18 | * - 2500 ms : device is suspended
19 | */
20 | enum {
21 | BLINK_NOT_MOUNTED = 250,
22 | BLINK_MOUNTED = 1000,
23 | BLINK_SUSPENDED = 2500,
24 | };
25 |
26 | static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED;
27 |
28 | void led_blinking_task(void);
29 | void cdc_task(void);
30 |
31 |
32 | #if !PICO_COPY_TO_RAM
33 | #error "This example must be built to run from SRAM!"
34 | #endif
35 |
36 | /*------------- MAIN -------------*/
37 | int main(void)
38 | {
39 | board_init();
40 |
41 | // init device stack on configured roothub port
42 | tusb_init();
43 |
44 | printReserveSectFat();
45 | printf("\n\nStart\n\n");
46 |
47 |
48 | while (1)
49 | {
50 | tud_task(); // tinyusb device task
51 | led_blinking_task();
52 | //printf("testing this out\n");
53 | //sleep_ms(100);
54 |
55 | }
56 |
57 | return 0;
58 | }
59 |
60 | //--------------------------------------------------------------------+
61 | // Device callbacks
62 | //--------------------------------------------------------------------+
63 |
64 | // Invoked when device is mounted
65 | void tud_mount_cb(void)
66 | {
67 | blink_interval_ms = BLINK_MOUNTED;
68 | }
69 |
70 | // Invoked when device is unmounted
71 | void tud_umount_cb(void)
72 | {
73 | blink_interval_ms = BLINK_NOT_MOUNTED;
74 | }
75 |
76 | // Invoked when usb bus is suspended
77 | // remote_wakeup_en : if host allow us to perform remote wakeup
78 | // Within 7ms, device must draw an average of current less than 2.5 mA from bus
79 | void tud_suspend_cb(bool remote_wakeup_en)
80 | {
81 | (void) remote_wakeup_en;
82 | blink_interval_ms = BLINK_SUSPENDED;
83 | }
84 |
85 | // Invoked when usb bus is resumed
86 | void tud_resume_cb(void)
87 | {
88 | blink_interval_ms = BLINK_MOUNTED;
89 | }
90 |
91 |
92 | //--------------------------------------------------------------------+
93 | // BLINKING TASK
94 | //--------------------------------------------------------------------+
95 | void led_blinking_task(void)
96 | {
97 | static uint32_t start_ms = 0;
98 | static bool led_state = false;
99 |
100 | // Blink every interval ms
101 | if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time
102 | start_ms += blink_interval_ms;
103 |
104 | board_led_write(led_state);
105 | led_state = 1 - led_state; // toggle
106 | }
107 |
--------------------------------------------------------------------------------
/tusb_config.h:
--------------------------------------------------------------------------------
1 | #ifndef _TUSB_CONFIG_H_
2 | #define _TUSB_CONFIG_H_
3 |
4 | #ifdef __cplusplus
5 | extern "C" {
6 | #endif
7 |
8 | //--------------------------------------------------------------------
9 | // COMMON CONFIGURATION
10 | //--------------------------------------------------------------------
11 |
12 | // defined by board.mk
13 | #ifndef CFG_TUSB_MCU
14 | #error CFG_TUSB_MCU must be defined
15 | #endif
16 |
17 | // RHPort number used for device can be defined by board.mk, default to port 0
18 | #ifndef BOARD_DEVICE_RHPORT_NUM
19 | #define BOARD_DEVICE_RHPORT_NUM 0
20 | #endif
21 |
22 | // RHPort max operational speed can defined by board.mk
23 | // Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed
24 | #ifndef BOARD_DEVICE_RHPORT_SPEED
25 | #if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \
26 | CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 || CFG_TUSB_MCU == OPT_MCU_SAMX7X)
27 | #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED
28 | #else
29 | #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED
30 | #endif
31 | #endif
32 |
33 | // Device mode with rhport and speed defined by board.mk
34 | #if BOARD_DEVICE_RHPORT_NUM == 0
35 | #define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED)
36 | #elif BOARD_DEVICE_RHPORT_NUM == 1
37 | #define CFG_TUSB_RHPORT1_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED)
38 | #else
39 | #error "Incorrect RHPort configuration"
40 | #endif
41 |
42 | #ifndef CFG_TUSB_OS
43 | #define CFG_TUSB_OS OPT_OS_NONE
44 | #endif
45 |
46 | // CFG_TUSB_DEBUG is defined by compiler in DEBUG build
47 | // #define CFG_TUSB_DEBUG 0
48 |
49 | /* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
50 | * Tinyusb use follows macros to declare transferring memory so that they can be put
51 | * into those specific section.
52 | * e.g
53 | * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") ))
54 | * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4)))
55 | */
56 | #ifndef CFG_TUSB_MEM_SECTION
57 | #define CFG_TUSB_MEM_SECTION
58 | #endif
59 |
60 | #ifndef CFG_TUSB_MEM_ALIGN
61 | #define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4)))
62 | #endif
63 |
64 | //--------------------------------------------------------------------
65 | // DEVICE CONFIGURATION
66 | //--------------------------------------------------------------------
67 |
68 | #ifndef CFG_TUD_ENDPOINT0_SIZE
69 | #define CFG_TUD_ENDPOINT0_SIZE 64
70 | #endif
71 |
72 | //------------- CLASS -------------//
73 | #define CFG_TUD_HID 0
74 | #define CFG_TUD_CDC 0
75 | #define CFG_TUD_MSC 1
76 | #define CFG_TUD_MIDI 0
77 | #define CFG_TUD_VENDOR 0
78 |
79 | // HID buffer size Should be sufficient to hold ID (if any) + Data
80 | #define CFG_TUD_HID_EP_BUFSIZE 16
81 | #define CFG_TUD_MSC_EP_BUFSIZE 512
82 |
83 | #ifdef __cplusplus
84 | }
85 | #endif
86 |
87 | #endif /* _TUSB_CONFIG_H_ */
88 |
--------------------------------------------------------------------------------
/fat12.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | //Not currently being used by default.
3 | //Just a example of a fat12 system
4 | //if you don't want the overhead of using fat16
5 | //From TinyUSB examples
6 | /*
7 |
8 | enum
9 | {
10 | DISK_BLOCK_NUM = 16, // 8KB is the smallest size that windows allow to mount
11 | DISK_BLOCK_SIZE = 512
12 | };
13 |
14 | uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] =
15 | {
16 | //------------- Block0: Boot Sector -------------//
17 | // byte_per_sector = DISK_BLOCK_SIZE; fat12_sector_num_16 = DISK_BLOCK_NUM;
18 | // sector_per_cluster = 1; reserved_sectors = 1;
19 | // fat_num = 1; fat12_root_entry_num = 16;
20 | // sector_per_fat = 1; sector_per_track = 1; head_num = 1; hidden_sectors = 0;
21 | // drive_number = 0x80; media_type = 0xf8; extended_boot_signature = 0x29;
22 | // filesystem_type = "FAT12 "; volume_serial_number = 0x1234; volume_label = "TinyUSB MSC";
23 | // FAT magic code at offset 510-511
24 | {
25 | 0xEB, 0x3C, 0x90, 0x4D, 0x53, 0x44, 0x4F, 0x53, 0x35, 0x2E, 0x30, 0x00, 0x02, 0x01, 0x01, 0x00,
26 | 0x01, 0x10, 0x00, 0x10, 0x00, 0xF8, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
27 | 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x29, 0x34, 0x12, 0x00, 0x00, 'T' , 'i' , 'n' , 'y' , 'U' ,
28 | 'S' , 'B' , ' ' , 'M' , 'S' , 'C' , 0x46, 0x41, 0x54, 0x31, 0x32, 0x20, 0x20, 0x20, 0x00, 0x00,
29 |
30 | // Zero up to 2 last bytes of FAT magic code
31 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
32 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
33 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
35 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
38 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
39 |
40 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
41 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
42 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
43 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
44 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
45 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
46 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
47 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
48 |
49 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
50 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
51 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
52 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
53 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
54 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
55 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
56 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
57 |
58 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
59 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
60 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
61 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xAA
62 | },
63 |
64 | //------------- Block1: FAT12 Table -------------//
65 | {
66 | 0xF8, 0xFF, 0xFF, 0xFF, 0x0F // // first 2 entries must be F8FF, third entry is cluster end of readme file
67 | },
68 |
69 | //------------- Block2: Root Directory -------------//
70 | {
71 | // first entry is volume label
72 | 'T' , 'i' , 'n' , 'y' , 'U' , 'S' , 'B' , ' ' , 'M' , 'S' , 'C' , 0x08, 0x00, 0x00, 0x00, 0x00,
73 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4F, 0x6D, 0x65, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
74 | // second entry is readme file
75 | 'R' , 'E' , 'A' , 'D' , 'M' , 'E' , ' ' , ' ' , 'T' , 'X' , 'T' , 0x20, 0x00, 0xC6, 0x52, 0x6D,
76 | 0x65, 0x43, 0x65, 0x43, 0x00, 0x00, 0x88, 0x6D, 0x65, 0x43, 0x02, 0x00,
77 | sizeof(README_CONTENTS)-1, 0x00, 0x00, 0x00 // readme's files size (4 Bytes)
78 | },
79 |
80 | //------------- Block3: Readme Content -------------//
81 | README_CONTENTS
82 | };
83 |
84 | //*/
--------------------------------------------------------------------------------
/usb_descriptors.c:
--------------------------------------------------------------------------------
1 | #include "tusb.h"
2 | #include "class/msc/msc.h"
3 | #include "device/usbd.h"
4 | /* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug.
5 | * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC.
6 | *
7 | * Auto ProductID layout's Bitmap:
8 | * [MSB] HID | MSC | CDC [LSB]
9 | */
10 | #define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) )
11 | #define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \
12 | _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) )
13 |
14 | #define USB_VID 0xCafe
15 | #define USB_BCD 0x0200
16 |
17 | //--------------------------------------------------------------------+
18 | // Device Descriptors
19 | //--------------------------------------------------------------------+
20 | tusb_desc_device_t const desc_device =
21 | {
22 | .bLength = sizeof(tusb_desc_device_t),
23 | .bDescriptorType = TUSB_DESC_DEVICE,
24 | .bcdUSB = USB_BCD,
25 |
26 | // Use Interface Association Descriptor (IAD) for CDC
27 | // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1)
28 | .bDeviceClass = TUSB_CLASS_MISC,
29 | .bDeviceSubClass = MISC_SUBCLASS_COMMON,
30 | .bDeviceProtocol = MISC_PROTOCOL_IAD,
31 |
32 | .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
33 |
34 | .idVendor = USB_VID,
35 | .idProduct = USB_PID,
36 | .bcdDevice = 0x0100,
37 |
38 | .iManufacturer = 0x01,
39 | .iProduct = 0x02,
40 | .iSerialNumber = 0x03,
41 |
42 | .bNumConfigurations = 0x01
43 | };
44 |
45 | // Invoked when received GET DEVICE DESCRIPTOR
46 | // Application return pointer to descriptor
47 | uint8_t const * tud_descriptor_device_cb(void)
48 | {
49 | return (uint8_t const *) &desc_device;
50 | }
51 |
52 | //--------------------------------------------------------------------+
53 | // Configuration Descriptor
54 | //--------------------------------------------------------------------+
55 |
56 | enum
57 | {
58 | ITF_NUM_MSC,
59 | ITF_NUM_TOTAL
60 | };
61 |
62 |
63 | #define EPNUM_MSC_OUT 0x01
64 | #define EPNUM_MSC_IN 0x81
65 |
66 |
67 | #define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_MSC_DESC_LEN)
68 |
69 | // full speed configuration
70 | uint8_t const desc_fs_configuration[] =
71 | {
72 | // Config number, interface count, string index, total length, attribute, power in mA
73 | TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
74 |
75 | // Interface number, string index, EP Out & EP In address, EP size
76 | TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 3 , EPNUM_MSC_OUT, EPNUM_MSC_IN, 64),
77 | };
78 |
79 | #if TUD_OPT_HIGH_SPEED
80 | // Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration
81 |
82 | // high speed configuration
83 | uint8_t const desc_hs_configuration[] =
84 | {
85 | // Config number, interface count, string index, total length, attribute, power in mA
86 | TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
87 | // Interface number, string index, EP Out & EP In address, EP size
88 | TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 3, EPNUM_MSC_OUT, EPNUM_MSC_IN, 512),
89 | };
90 |
91 | // other speed configuration
92 | uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN];
93 |
94 | // device qualifier is mostly similar to device descriptor since we don't change configuration based on speed
95 | tusb_desc_device_qualifier_t const desc_device_qualifier =
96 | {
97 | .bLength = sizeof(tusb_desc_device_qualifier_t),
98 | .bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER,
99 | .bcdUSB = USB_BCD,
100 |
101 | .bDeviceClass = TUSB_CLASS_MISC,
102 | .bDeviceSubClass = MISC_SUBCLASS_COMMON,
103 | .bDeviceProtocol = MISC_PROTOCOL_IAD,
104 |
105 | .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
106 | .bNumConfigurations = 0x01,
107 | .bReserved = 0x00
108 | };
109 |
110 | // Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request
111 | // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete.
112 | // device_qualifier descriptor describes information about a high-speed capable device that would
113 | // change if the device were operating at the other speed. If not highspeed capable stall this request.
114 | uint8_t const* tud_descriptor_device_qualifier_cb(void)
115 | {
116 | return (uint8_t const*) &desc_device_qualifier;
117 | }
118 |
119 | // Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request
120 | // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
121 | // Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa
122 | uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index)
123 | {
124 | (void) index; // for multiple configurations
125 |
126 | // if link speed is high return fullspeed config, and vice versa
127 | // Note: the descriptor type is OHER_SPEED_CONFIG instead of CONFIG
128 | memcpy(desc_other_speed_config,
129 | (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_fs_configuration : desc_hs_configuration,
130 | CONFIG_TOTAL_LEN);
131 |
132 | desc_other_speed_config[1] = TUSB_DESC_OTHER_SPEED_CONFIG;
133 |
134 | return desc_other_speed_config;
135 | }
136 |
137 | #endif // highspeed
138 |
139 |
140 | // Invoked when received GET CONFIGURATION DESCRIPTOR
141 | // Application return pointer to descriptor
142 | // Descriptor contents must exist long enough for transfer to complete
143 | uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
144 | {
145 | (void) index; // for multiple configurations
146 |
147 | #if TUD_OPT_HIGH_SPEED
148 | // Although we are highspeed, host may be fullspeed.
149 | return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_hs_configuration : desc_fs_configuration;
150 | #else
151 | return desc_fs_configuration;
152 | #endif
153 | }
154 |
155 | //--------------------------------------------------------------------+
156 | // String Descriptors
157 | //--------------------------------------------------------------------+
158 |
159 | // array of pointer to string descriptors
160 | char const* string_desc_arr [] =
161 | {
162 | (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
163 | "TinyUSB", // 1: Manufacturer
164 | "TinyUSB Device", // 2: Product
165 | "RPI-RP2", // 3: MSC Interface
166 | };
167 |
168 | static uint16_t _desc_str[32];
169 |
170 | // Invoked when received GET STRING DESCRIPTOR request
171 | // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
172 | uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid)
173 | {
174 | (void) langid;
175 |
176 | uint8_t chr_count;
177 |
178 | if ( index == 0)
179 | {
180 | memcpy(&_desc_str[1], string_desc_arr[0], 2);
181 | chr_count = 1;
182 | }else
183 | {
184 | // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors.
185 | // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors
186 |
187 | if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL;
188 |
189 | const char* str = string_desc_arr[index];
190 |
191 | // Cap at max char
192 | chr_count = (uint8_t) strlen(str);
193 | if ( chr_count > 31 ) chr_count = 31;
194 |
195 | // Convert ASCII string into UTF-16
196 | for(uint8_t i=0; i
7 | #include "checkUF2.h"
8 | // whether host does safe-eject
9 | static bool ejected = false;
10 |
11 | // Some MCU doesn't have enough 8KB SRAM to store the whole disk
12 | // We will use Flash as read-only disk with board that has
13 |
14 | void software_reset()
15 | {
16 | watchdog_enable(1, 1);
17 | while(1);
18 | }
19 |
20 | #define HTML_Page_Data \
21 | R"(Redirecting to raspberrypi.com)"
22 |
23 |
24 | #define DATA_Page_Data \
25 | "UF2 Bootloader v3.0\n\
26 | Model: Raspberry Pi RP2\n\
27 | Board-ID: RPI-RP2\n"
28 |
29 |
30 | enum
31 | {
32 | DISK_BLOCK_NUM = 0x3ffff, // 8KB is the smallest size that windows allow to mount
33 | DISK_BLOCK_SIZE = 512,
34 | DISK_CLUSTER_SIZE = 8
35 | };
36 |
37 | //indexs of places
38 | enum
39 | {
40 | INDEX_RESERVED = 0,
41 | INDEX_FAT_TABLE_1_START = 1, //Fat table size is 0x81
42 | INDEX_FAT_TABLE_2_START = 0x82,
43 | INDEX_ROOT_DIRECTORY = 0x103,
44 | INDEX_DATA_STARTS = 0x123,
45 | INDEX_DATA_END = (0x12b + DISK_CLUSTER_SIZE - 1)
46 | };
47 |
48 |
49 | #define MAX_SECTION_COUNT_FOR_FLASH_SECTION (FLASH_SECTOR_SIZE/FLASH_PAGE_SIZE)
50 | struct flashingLocation {
51 | unsigned int pageCountFlash;
52 | }flashingLocation = {.pageCountFlash = 0};
53 |
54 |
55 | uint8_t DISK_reservedSection[DISK_BLOCK_SIZE] =
56 | {
57 | 0xEB, 0x3C, 0x90,
58 | 0x4D, 0x53, 0x57, 0x49, 0x4E, 0x34, 0x2E, 0x31, //MSWIN4.1
59 | 0x00, 0x02, //sector 512
60 | 0x08, //cluster size 8 sectors -unit for file sizes
61 | 0x01, 0x00, //BPB_RsvdSecCnt
62 | 0x02, //Number of fat tables
63 | 0x00, 0x02, //BPB_RootEntCnt
64 | 0x00, 0x00, //16 bit fat sector count - 0 larger then 0x10000
65 | 0xF8, //- non-removable disks a
66 | 0x81, 0x00, //BPB_FATSz16 - Size of fat table
67 | 0x01, 0x00, //BPB_SecPerTrk
68 | 0x01, 0x00, //BPB_NumHeads
69 | 0x01, 0x00, 0x00, 0x00, //??? BPB_HiddSec
70 | 0xFF, 0xFF, 0x03, 0x00, //BPB_TotSec32
71 | 0x00, //BS_DrvNum - probably be 0x80 but is not?
72 | 0x00, //
73 | 0x29,
74 | 0x50, 0x04, 0x0B, 0x00, //Volume Serial Number
75 | 'R' , 'P' , 'I' , '-' , 'R' , 'P' , '2' , ' ' , ' ' , ' ' , ' ' ,
76 | 'F', 'A', 'T', '1', '6', ' ', ' ', ' ',
77 |
78 | 0x00, 0x00,
79 |
80 | // Zero up to 2 last bytes of FAT magic code
81 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
82 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
83 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
84 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
85 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
86 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
87 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
88 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
89 |
90 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
91 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
92 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
93 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
94 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
95 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
96 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
97 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
98 |
99 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
100 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
101 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
102 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
103 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
104 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
105 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
106 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
107 |
108 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
109 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
110 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
111 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xAA
112 | };
113 |
114 | uint8_t DISK_fatTable[DISK_BLOCK_SIZE] =
115 | {
116 | 0xF8, 0xFF,
117 | 0xFF, 0xFF,
118 | 0xFF, 0xFF, //HTML doc
119 | 0xFF, 0xFF, //Txt file
120 | };
121 |
122 |
123 | uint8_t DISK_rootDirectory[DISK_BLOCK_SIZE] =
124 | {
125 | // first entry is volume label
126 | 'R' , 'P' , 'I' , '-' , 'R' , 'P' , '2' , ' ' , ' ' , ' ' , ' ' , 0x28, 0x00, 0x00, 0x00, 0x00,
127 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0, 0x0, 0x0, 0x0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
128 | // second entry is html file
129 | 'I' , 'N' , 'D' , 'E' , 'X' , ' ' , ' ' , ' ' , 'H' , 'T' , 'M' , 0x21, 0x00, 0xC6, 0x52, 0x6D,
130 | 0x65, 0x43, 0x65, 0x43, 0x00, 0x00, 0x88, 0x6D, 0x65, 0x43,
131 | 0x02, 0x00, //cluster location
132 | 0xF1, 0x00, 0x00, 0x00, // html's files size (4 Bytes)
133 | // third entry is text file
134 | 'I' , 'N' , 'F' , 'O' , '_' , 'U' , 'F' , '2' , 'T' , 'X' , 'T' , 0x21, 0x00, 0xC6, 0x52, 0x6D,
135 | 0x65, 0x43, 0x65, 0x43, 0x00, 0x00, 0x88, 0x6D, 0x65, 0x43,
136 | 0x03, 0x00, //cluster location
137 | 0x3E, 0x00, 0x00, 0x00 // readme's files size (4 Bytes)
138 | };
139 |
140 | //block size is not cluster size
141 | uint8_t DISK_data[2][DISK_BLOCK_SIZE] =
142 | {
143 | {HTML_Page_Data},
144 | {DATA_Page_Data}
145 | };
146 |
147 |
148 |
149 |
150 | void printReserveSectFat()
151 | {
152 | printReserveSect((ReserveSect*)DISK_reservedSection);
153 | }
154 |
155 | // Invoked when received SCSI_CMD_INQUIRY
156 | // Application fill vendor id, product id and revision with string up to 8, 16, 4 characters respectively
157 | void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4])
158 | {
159 | (void) lun;
160 |
161 | const char vid[] = "TinyUSB";
162 | const char pid[] = "Mass Storage";
163 | const char rev[] = "1.0";
164 |
165 | memcpy(vendor_id , vid, strlen(vid));
166 | memcpy(product_id , pid, strlen(pid));
167 | memcpy(product_rev, rev, strlen(rev));
168 | }
169 |
170 | // Invoked when received Test Unit Ready command.
171 | // return true allowing host to read/write this LUN e.g SD card inserted
172 | bool tud_msc_test_unit_ready_cb(uint8_t lun)
173 | {
174 | (void) lun;
175 |
176 | // RAM disk is ready until ejected
177 | if (ejected) {
178 | // Additional Sense 3A-00 is NOT_FOUND
179 | tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x3a, 0x00);
180 | return false;
181 | }
182 |
183 | return true;
184 | }
185 |
186 | // Invoked when received SCSI_CMD_READ_CAPACITY_10 and SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size
187 | // Application update block count and block size
188 | void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size)
189 | {
190 | (void) lun;
191 |
192 | *block_count = DISK_BLOCK_NUM;
193 | *block_size = DISK_BLOCK_SIZE;
194 | }
195 |
196 | // Invoked when received Start Stop Unit command
197 | // - Start = 0 : stopped power mode, if load_eject = 1 : unload disk storage
198 | // - Start = 1 : active mode, if load_eject = 1 : load disk storage
199 | bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject)
200 | {
201 | (void) lun;
202 | (void) power_condition;
203 |
204 | if ( load_eject )
205 | {
206 | if (start)
207 | {
208 | // load disk storage
209 | }else
210 | {
211 | // unload disk storage
212 | ejected = true;
213 | }
214 | }
215 |
216 | return true;
217 | }
218 |
219 | // Callback invoked when received READ10 command.
220 | // Copy disk's data to buffer (up to bufsize) and return number of copied bytes.
221 | int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize)
222 | {
223 | (void) lun;
224 |
225 | // out of ramdisk
226 | if ( lba >= DISK_BLOCK_NUM ) return -1;
227 | //printf("lba 0x%x, bufsize %d, offset %d\n",lba, bufsize, offset);
228 | //uint8_t const* addr = msc_disk[lba] + offset;
229 | //memcpy(buffer, addr, bufsize);
230 |
231 | uint8_t * addr = 0;
232 | if(lba == INDEX_RESERVED)
233 | {
234 | addr = DISK_reservedSection;
235 | }
236 | else if(lba == INDEX_FAT_TABLE_1_START || lba == INDEX_FAT_TABLE_2_START)
237 | {
238 | addr = DISK_fatTable;
239 | }
240 | else if(lba == INDEX_ROOT_DIRECTORY)
241 | {
242 | addr = DISK_rootDirectory;
243 | }
244 | else if(lba >= INDEX_DATA_STARTS && lba <= INDEX_DATA_END )
245 | {
246 | //printf("lba %d, bufsize %d, offset %d\n",lba, bufsize, offset);
247 | //DISK_data is only one section large but the cluster sizes are 8.
248 | //So if there was a larger file it would be bad.
249 | addr = DISK_data[(lba - INDEX_DATA_STARTS) / 8];
250 | //printf("loading section %d\n",(lba - INDEX_DATA_STARTS) / 8);
251 | }
252 | if(addr != 0)
253 | {
254 | memcpy(buffer, addr, bufsize);
255 | }
256 | else{
257 | memset(buffer,0, bufsize);
258 | }
259 | return (int32_t) bufsize;
260 | }
261 |
262 | bool tud_msc_is_writable_cb (uint8_t lun)
263 | {
264 | (void) lun;
265 |
266 |
267 | return true;
268 | }
269 |
270 | // Callback invoked when received WRITE10 command.
271 | // Process data in buffer to disk's storage and return number of written bytes
272 | int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize)
273 | {
274 | (void) lun;
275 | printf("write - lba 0x%x, bufsize%d\n", lba,bufsize);
276 |
277 | // out of ramdisk
278 | if ( lba >= DISK_BLOCK_NUM ) return -1;
279 | //page to sector
280 | if(lba >= INDEX_DATA_END){
281 | //memcpy(&flashingLocation.buff[flashingLocation.sectionCount * 512], buffer, bufsize);
282 | //uint32_t ints = save_and_disable_interrupts();
283 | if(flashingLocation.pageCountFlash % MAX_SECTION_COUNT_FOR_FLASH_SECTION == 0)
284 | {
285 | printf("doing flash at offset 0x%x\n",flashingLocation.pageCountFlash * FLASH_PAGE_SIZE);
286 | flash_range_erase((flashingLocation.pageCountFlash / 16) * FLASH_SECTOR_SIZE, FLASH_SECTOR_SIZE);
287 | }
288 | unsigned int * returnSize;
289 | unsigned char *addressUF2 = getUF2Info(buffer,returnSize);
290 | if(addressUF2 != 0)
291 | {
292 | printf("UF2 FILE %d!!!\n",flashingLocation.pageCountFlash );
293 | flash_range_program(flashingLocation.pageCountFlash * FLASH_PAGE_SIZE,
294 | &buffer[32],
295 | 256);
296 | flashingLocation.pageCountFlash += 1; //(*returnSize/ FLASH_PAGE_SIZE);
297 | }
298 | else{
299 | flash_range_program(flashingLocation.pageCountFlash * FLASH_PAGE_SIZE,
300 | buffer,
301 | bufsize);
302 | flashingLocation.pageCountFlash += (bufsize/ FLASH_PAGE_SIZE);
303 | }
304 | }
305 |
306 | if(lba == INDEX_ROOT_DIRECTORY)
307 | {
308 | printf("\n\n\nRestarting the raspberry pi pico!!!! \n\n\n");
309 | sleep_ms(100);//just to make sure all uart get out
310 |
311 | software_reset();
312 | }
313 |
314 | //#ifndef CFG_EXAMPLE_MSC_READONLY
315 | // uint8_t* addr = msc_disk[lba] + offset;
316 | // memcpy(addr, buffer, bufsize);
317 | //#else
318 |
319 |
320 | return (int32_t) bufsize;
321 | }
322 |
323 | // Callback invoked when received an SCSI command not in built-in list below
324 | // - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, MODE_SENSE6, REQUEST_SENSE
325 | // - READ10 and WRITE10 has their own callbacks
326 | int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize)
327 | {
328 | // read10 & write10 has their own callback and MUST not be handled here
329 |
330 | void const* response = NULL;
331 | int32_t resplen = 0;
332 |
333 | // most scsi handled is input
334 | bool in_xfer = true;
335 |
336 | switch (scsi_cmd[0])
337 | {
338 | default:
339 | // Set Sense = Invalid Command Operation
340 | tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00);
341 |
342 | // negative means error -> tinyusb could stall and/or response with failed status
343 | resplen = -1;
344 | break;
345 | }
346 |
347 | // return resplen must not larger than bufsize
348 | if ( resplen > bufsize ) resplen = bufsize;
349 |
350 | if ( response && (resplen > 0) )
351 | {
352 | if(in_xfer)
353 | {
354 | memcpy(buffer, response, (size_t) resplen);
355 | }else
356 | {
357 | // SCSI output
358 | }
359 | }
360 |
361 | return (int32_t) resplen;
362 | }
363 |
--------------------------------------------------------------------------------