1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _PICOBOOT_CONNECTION_H
#define _PICOBOOT_CONNECTION_H
// todo we should use fully encapsulate libusb
#include <assert.h>
#if HAS_LIBUSB
#include <libusb.h>
#endif
#include "boot/picoboot.h"
#include "addresses.h"
#define VENDOR_ID_RASPBERRY_PI 0x2e8au
#define PRODUCT_ID_RP2040_USBBOOT 0x0003u
#define PRODUCT_ID_PICOPROBE 0x0004u
#define PRODUCT_ID_MICROPYTHON 0x0005u
#define PRODUCT_ID_STDIO_USB 0x0009u
#define PRODUCT_ID_RP2040_STDIO_USB 0x000au
#define PRODUCT_ID_RP2350_USBBOOT 0x000fu
#ifdef __cplusplus
extern "C" {
#endif
enum picoboot_device_result {
dr_vidpid_bootrom_ok,
dr_vidpid_bootrom_no_interface,
dr_vidpid_bootrom_cant_connect,
dr_vidpid_micropython,
dr_vidpid_picoprobe,
dr_vidpid_unknown,
dr_error,
dr_vidpid_stdio_usb,
};
typedef enum {
rp2040,
rp2350,
unknown
} model_t;
typedef enum {
rp2350_a2,
rp2350_unknown
} rp2350_version_t;
#if HAS_LIBUSB
// note that vid and pid are filters, unless both are specified in which case a device with that VID and PID is allowed for RP2350
enum picoboot_device_result picoboot_open_device(libusb_device *device, libusb_device_handle **dev_handle, model_t *model, int vid, int pid, const char* ser);
int picoboot_reset(libusb_device_handle *usb_device);
int picoboot_cmd_status_verbose(libusb_device_handle *usb_device, struct picoboot_cmd_status *status,
bool local_verbose);
int picoboot_cmd_status(libusb_device_handle *usb_device, struct picoboot_cmd_status *status);
int picoboot_exclusive_access(libusb_device_handle *usb_device, uint8_t exclusive);
int picoboot_enter_cmd_xip(libusb_device_handle *usb_device);
int picoboot_exit_xip(libusb_device_handle *usb_device);
int picoboot_reboot(libusb_device_handle *usb_device, uint32_t pc, uint32_t sp, uint32_t delay_ms);
int picoboot_reboot2(libusb_device_handle *usb_device, struct picoboot_reboot2_cmd *reboot_cmd);
int picoboot_get_info(libusb_device_handle *usb_device, struct picoboot_get_info_cmd *cmd, uint8_t *buffer, uint32_t len);
int picoboot_exec(libusb_device_handle *usb_device, uint32_t addr);
// int picoboot_exec2(libusb_device_handle *usb_device, struct picoboot_exec2_cmd *exec2_cmd); // currently unused
int picoboot_flash_erase(libusb_device_handle *usb_device, uint32_t addr, uint32_t len);
int picoboot_vector(libusb_device_handle *usb_device, uint32_t addr);
int picoboot_write(libusb_device_handle *usb_device, uint32_t addr, uint8_t *buffer, uint32_t len);
int picoboot_read(libusb_device_handle *usb_device, uint32_t addr, uint8_t *buffer, uint32_t len);
int picoboot_otp_write(libusb_device_handle *usb_device, struct picoboot_otp_cmd *otp_cmd, uint8_t *buffer, uint32_t len);
int picoboot_otp_read(libusb_device_handle *usb_device, struct picoboot_otp_cmd *otp_cmd, uint8_t *buffer, uint32_t len);
int picoboot_poke(libusb_device_handle *usb_device, uint32_t addr, uint32_t data);
int picoboot_peek(libusb_device_handle *usb_device, uint32_t addr, uint32_t *data);
int picoboot_flash_id(libusb_device_handle *usb_device, uint64_t *data);
#endif
// we require 256 (as this is the page size supported by the device)
#define LOG2_PAGE_SIZE 8u
#define PAGE_SIZE (1u << LOG2_PAGE_SIZE)
#define FLASH_SECTOR_ERASE_SIZE 4096u
enum memory_type {
rom,
flash,
sram,
sram_unstriped,
xip_sram,
invalid,
};
// inclusive of ends
static inline enum memory_type get_memory_type(uint32_t addr, model_t model) {
if (addr >= FLASH_START && addr <= FLASH_END_RP2040) {
return flash;
}
if (addr >= ROM_START && addr <= ROM_END_RP2040) {
return rom;
}
if (addr >= SRAM_START && addr <= SRAM_END_RP2040) {
return sram;
}
if (model == rp2350) {
if (addr >= FLASH_START && addr <= FLASH_END_RP2350) {
return flash;
}
if (addr >= ROM_START && addr <= ROM_END_RP2350) {
return rom;
}
if (addr >= SRAM_START && addr <= SRAM_END_RP2350) {
return sram;
}
}
if (addr >= MAIN_RAM_BANKED_START && addr <= MAIN_RAM_BANKED_END) {
return sram_unstriped;
}
if (model == rp2040) {
if (addr >= XIP_SRAM_START_RP2040 && addr <= XIP_SRAM_END_RP2040) {
return xip_sram;
}
} else if (model == rp2350) {
if (addr >= XIP_SRAM_START_RP2350 && addr <= XIP_SRAM_END_RP2350) {
return xip_sram;
}
}
return invalid;
}
static inline bool is_transfer_aligned(uint32_t addr, model_t model) {
enum memory_type t = get_memory_type(addr, model);
return t != invalid && !(t == flash && addr & (PAGE_SIZE-1));
}
static inline bool is_size_aligned(uint32_t addr, int size) {
#ifndef _MSC_VER
assert(__builtin_popcount(size)==1);
#endif
return !(addr & (size-1));
}
#ifdef __cplusplus
}
#endif
#endif
|