This repository has been archived by the owner on Aug 9, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 28
/
flash
executable file
·320 lines (265 loc) · 9.14 KB
/
flash
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
#!/bin/bash
# port esp32 is connected to (leave empty to autodetect)
PORT=
#PORT=/dev/ttyUSB1
# baud rate for programming
FLASH_BAUDRATE=921600
# baud rate for terminal
TERM_BAUDRATE=115200
# Flash Mode
FLASH_MODE="dio"
# Flash Speed
FLASH_SPEED="40m"
# Use bootloader (needed for using irom, drom and psram)
USE_BOOTLOADER=1
# debug or release build
TYPE=debug
# address of partition table
PARTION_ADDR=0x8000
# address of application
APP_ADDR=0x10000
#source of the utility to generate the binary partition table
GENPART_SOURCE=https://github.com/espressif/esp-idf/blob/v4.0/components/partition_table/gen_esp32part.py?raw=true
# source of the bootloader
# customized bootloader which initializes the external psram
BOOTLOADER_SOURCE=https://github.com/arjanmels/esp32_bootloader_init_extram/blob/v1.0/build/bootloader/bootloader.bin?raw=true
# default bootloader from the espressif arduino github
#BOOTLOADER_SOURCE=https://github.com/espressif/arduino-esp32/blob/idf-release/v4.0/tools/sdk/bin/bootloader_dio_40m.bin?raw=true
# color codes
STAGE="\033[1;36m"
SUCCESS="\033[1;32m"
ERROR="\033[1;31m"
RESET="\033[0m"
showhelp() {
cat << EOF
Usage: flash -hrtbs [-p <serial port>] [-e <example>]
-h, --help Display Help
-r, --release Build in release mode
-p, --port <serial port> Set serial port (default: autodetect)
-b, --baudrate <baudrate> Set baudrate for flasing (default: $FLASH_BAUDRATE)
, --termbaudrate <baudrate> Set baudrate for monitoring (default: $TERM_BAUDRATE)
-t, --terminal Open terminal program after flashing
-e, --example <example> Build the specified example
-s, --skip Skip actual flashing
EOF
}
# get command line options
options=$(getopt -l "help,release,port:,terminal,baudrate:,termbaudrate:,example:,skip" -o "hrp:tb:e:s" -a -- "$@")
if [[ $? -ne 0 ]]
then
echo
showhelp
exit 1
fi
eval set -- "$options"
while true
do
case $1 in
-h|--help)
showhelp
exit 0
;;
-r|--release)
export TYPE=release
;;
-p|--port)
shift
export PORT=$1
;;
-s|--skip)
export SKIPFLASH=1
;;
-t|--terminal)
export TERMINAL=1
;;
-b|--baudrate)
shift
export FLASH_BAUDRATE=$1
;;
--termbaudrate)
shift
export TERM_BAUDRATE=$1
;;
-e|--example)
shift
export EXAMPLE=$1
;;
--)
shift
break;;
esac
shift
done
if [[ $# -ne 0 ]]
then
printf "${ERROR}*** Wrong number of arguments${RESET}\n\n" >&2
showhelp
exit 1
fi
if [[ ! -f Cargo.toml ]]
then
printf "${ERROR}*** Must be run in root of project where Cargo.toml file is located${RESET}\n" >&2
exit 1
fi
if [[ -z "$EXAMPLE" ]]
then
FILE=$(awk 'BEGIN {FS="[ \t=\"]+";} /^\s*\[/ {section=$1} tolower(section)=="[package]" && tolower($0) ~ /^\s*name/ {print $2}' Cargo.toml)
BIN_PATH=target/xtensa-esp32-none-elf/$TYPE/$FILE
EXAMPLE_ARG=""
else
BIN_PATH=target/xtensa-esp32-none-elf/$TYPE/examples/$EXAMPLE
EXAMPLE_ARG="--example "$EXAMPLE
fi
# set the release flag
if [ "$TYPE" = "release" ]
then
RELEASE="--release"
else
RELEASE=""
fi
CMD="cargo xbuild $RELEASE $EXAMPLE_ARG"
printf "${STAGE}Building application with $CMD...${RESET}\n\n"
rm target/current.elf 2> /dev/null
rm target/current.bin 2> /dev/null
# get error code of any step of the pipe
set -o pipefail
# run cargo & get missing features
{ FEATURES=$(script -efqc "$CMD 2>&1" /dev/null | tee /dev/stderr | egrep -o '\-\-features=".*"'; exit ${PIPESTATUS[0]}); }
RES=$?
# if cargo returned an error because features are missing to rerun
if [[ $RES -ne 0 && -n $FEATURES ]]
then
CMD="cargo xbuild $RELEASE $EXAMPLE_ARG $FEATURES"
printf "\n\n${STAGE}Building application with $CMD...${RESET}\n\n"
eval $CMD
RES=$?
fi
# if cargo returned an error exit
if [[ $RES -ne 0 ]]
then
exit 1
fi
if [[ ! -f $BIN_PATH ]]
then
printf "${ERROR}Error: Output file ($BIN_PATH) not generated!${RESET}\n\n"
exit 1
fi
#display section sizes
echo
xtensa-esp32-elf-readelf $BIN_PATH -S|egrep 'BIT|\[Nr\]' |awk 'BEGIN {FS="[ \t\[\]]+"} $9~/A|Flg/ {size=sprintf("%7d", "0x" $7)+0; printf("%-3s %-20s %-8s %-8s %-8s %8s %-3s %-3s\n",$2,$3,$4,$5,$7,((size>0)?size:$7),$9,$12); total+=size; } END { printf("\nTotal: %d bytes\n",total)}'
echo
# convert to bin
rm $BIN_PATH.bin 2>/dev/null
esptool.py --chip esp32 elf2image --flash_mode=$FLASH_MODE --flash_freq $FLASH_SPEED -o $BIN_PATH.bin $BIN_PATH > /dev/null
if [ $? -ne 0 ]
then
printf "${ERROR}Error: Output file ($BIN_PATH).bin not generated!${RESET}\n\n"
esptool.py --chip esp32 elf2image --flash_mode=$FLASH_MODE --flash_freq $FLASH_SPEED -o $BIN_PATH.bin $BIN_PATH
exit 1
fi
esptool.py --chip esp32 image_info $BIN_PATH.bin |egrep -v -i "esptool.py|Image version|Checksum|Validation Hash|Segments"
echo
if [ $? -ne 0 ]
then
exit 1
fi
# create links to output binaries for linking with debugger
ln -sf $(pwd)/$BIN_PATH target/current.elf
ln -sf $(pwd)/$BIN_PATH.bin target/current.bin
if [[ $SKIPFLASH -ne 1 || $TERMINAL -eq 1 ]]
then
if [[ -z "$PORT" ]]
then
# kill terminal programs using any port
ps -ef|grep "/dev/ttyUSB" |egrep -v "$0|grep" |awk '{print $2}'|xargs -r kill
printf "${STAGE}Detecting port...${RESET} "
PORT=$(esptool.py --no-stub read_mac 2> /dev/null | awk '/^Serial port / {port=$3} END {print port}')
if [[ -z $PORT ]]
then
printf "${ERROR}Error: cannot detect port!${RESET}\n\n"
exit 1
fi
printf "$PORT\n\n"
else
# kill terminal programs using the same port
ps -ef|grep $PORT|egrep -v "$0|grep" |awk '{print $2}'|xargs -r kill
fi
fi
if [[ $SKIPFLASH -ne 1 ]]
then
flash() {
echo -e "${STAGE}Flashing...${RESET} $@\n"
esptool.py --chip esp32 --port $PORT --baud $FLASH_BAUDRATE --after hard_reset write_flash --flash_mode=$FLASH_MODE --flash_freq $FLASH_SPEED --flash_size detect ${@} |egrep -v -i "stub|baud rate|Changed.|Configuring flash size|Serial port|esptool.py|Leaving"
}
if [[ !USE_BOOTLOADER -eq 1 ]]
then
flash 0x1000 $BIN_PATH.bin
else
printf "${STAGE}Creating partition table... ${RESET}"
if [[ target/partitions.bin -ot partitions.csv ]]
then
printf "\n\n"
# get gen_esp32part.py and create binary partition table
curl -s -S -f --max-time 5 -L $GENPART_SOURCE --output target/gen_esp32part.py_new
if [ $? -ne 0 ]; then
if [ -f target/gen_esp32part.py ]; then
printf "\n${ERROR}Failed to get gen_esp32part.py${RESET} using old one\n\n"
else
printf "\n${ERROR}Failed to get gen_esp32part.py${RESET}\n\n"
exit 1
fi
else
mv target/gen_esp32part.py_new target/gen_esp32part.py
fi
rm target/partitions.bin 2> /dev/null
python target/gen_esp32part.py partitions.csv target/partitions.bin
echo
else
printf "skipping as it is up to date\n\n"
fi
printf "${STAGE}Getting bootloader... ${RESET}"
# get bootloader.bin file
# (different variants exist, but only difference is flash settings which are overriden by esptool)
curl -s -S -f --max-time 5 -L $BOOTLOADER_SOURCE --output target/bootloader.bin_new
if [ $? -ne 0 ]; then
if [ -f target/bootloader.bin ]; then
printf "\n${ERROR}Failed to get bootloader${RESET} using old one\n\n"
else
printf "\n${ERROR}Failed to get bootloader${RESET}\n\n"
exit 1
fi
else
mv target/bootloader.bin_new target/bootloader.bin
printf "succesfully downloader bootloader\n\n"
fi
# check if bootloader.bin and paritions.bin are already correctly flashed (to prevent unnecessary writes)
printf "${STAGE}Verify bootloader and partition table...${RESET} "
esptool.py --no-stub --chip esp32 --port $PORT --baud $FLASH_BAUDRATE verify_flash 0x1000 target/bootloader.bin $PARTION_ADDR target/partitions.bin > /dev/null
if [ $? -ne 0 ]; then
printf "modified\n\n"
# flash bootloader.bin, partitions.bin and application
flash 0x1000 target/bootloader.bin $PARTION_ADDR target/partitions.bin $APP_ADDR $BIN_PATH.bin
else
printf "unchanged\n\n"
# flash application only
flash $APP_ADDR $BIN_PATH.bin
fi
fi
if [[ $? -ne 0 ]]
then
printf "\n${ERROR}Error flashing application${RESET}\n\n"
exit 1
fi
fi
# start terminal program
if [[ TERMINAL -eq 1 ]]
then
printf "\n${STAGE}Starting terminal.${RESET}\n"
gnome-terminal --geometry 200x15+0+9999 -- picocom -b $TERM_BAUDRATE $PORT --imap lfcrlf 2>/dev/null
fi
if [[ $SKIPFLASH -ne 1 ]]
then
printf "\n${SUCCESS}Succesfully build and flashed application${RESET}\n\n"
else
printf "\n${SUCCESS}Succesfully build application${RESET}\n\n"
fi