prog_fuse.sh: fix this script when using dash
[aversive.git] / config / prog_fuses.sh
1 #!/bin/sh
2
3 # bit $1 is set in $2 (8 bits)
4 bit_is_set() {
5         if [ $(($2 & $((1 << $1)))) -eq 0 ]; then
6                 return 0
7         else
8                 return 1
9         fi
10 }
11
12 # $1 = name
13 # $2 = value
14 disp_fuse() {
15         echo -n "$1: "
16         bit=7
17         while [ $bit -ge 0 ]; do
18                 NAME=`cut -d ' ' -f 2- ${MCU_DESC_FILE} | grep "^$bit $1" | cut -d ' ' -f 3`
19                 if [ -z "$NAME" ]; then
20                         echo -n "XXXX"
21                 else
22                         bit_is_set $bit $2
23                         bitval=$?
24                         echo -n "$NAME=$bitval"
25                 fi
26                 echo -n " "
27                 bit=$(($bit-1))
28         done
29         echo
30 }
31
32 # $1 filename
33 intel2hex() {
34         echo "0x`cat $1 | head -1 | cut -b10-11`" > $1.tmp
35         mv $1.tmp $1
36 }
37
38 # $1 filename
39 hex2intel() {
40         printf ":01000000%.2X" `cat $1` > $1.tmp
41         printf "%.2X\n" $((0xFF - `cat $1`)) >> $1.tmp
42         echo ":00000001FF" >> $1.tmp
43         mv $1.tmp $1
44 }
45
46
47 # 1/ read fuse state if possible
48 # 2/ prompt every bit
49 # 3/ program
50
51 MCU_DESC_FILE=$1
52
53 echo "----------------------------------------------------------"
54 echo "                   Programming fuses"
55 echo "----------------------------------------------------------"
56 echo
57 echo "Warning : It can bue dangerous to program your fuses: some"
58 echo "configurations will prevent you to program your uC. Be sure"
59 echo "that you have carrefully read the documentation, and that"
60 echo "you know what you're doing"
61 echo
62 echo "Warning : 0 means programmed and 1 means unprogrammed (see"
63 echo "AVR documentation for details"
64 echo
65 echo "BIT FAT WARNING ! PLEASE CHECK THE DOCUMENTATION BEFORE"
66 echo "PROGRAMMING BECAUSE SOME PARTS HAVE NOT BEEN TESTED"
67 echo
68
69 while true; do
70         echo -n "Are you sure ? [y/n] "
71         read ans
72
73         case $ans in
74                 y|Y)
75                         break
76                         ;;
77                 n|N)
78                         echo " abort..."
79                         exit 0
80                         ;;
81                 *)
82                         echo " Please type 'y' or 'n'"
83         esac
84 done
85
86 if [ ! -f ${MCU_DESC_FILE} ]; then
87         echo "ERROR"
88         echo "Can't find the file ${MCU_DESC_FILE}"
89         echo "If `basename ${MCU_DESC_FILE}` is a valid uC, you should add it in"
90         echo "AVERSIVE/config/fuses_defs directory"
91         exit 1
92 fi
93
94 if [ -z "${PROGRAMMER}" ]; then
95         echo "ERROR !"
96         echo " PROGRAMMER variable is not defined, check that the script"
97         echo " is launched from a 'make fuse' in project directory"
98         exit 1
99 fi
100
101 if [ "${PROGRAMMER}" = "avrdude" -a -z "${AVRDUDE}" ]; then
102         echo "ERROR !"
103         echo " AVRDUDE variable is not defined, check that the script"
104         echo " is launched from a 'make fuse' in project directory"
105         exit 1
106 fi
107
108 if [ "${AVARICE}" = "avarice" -a -z "${AVARICE}" ]; then
109         echo "ERROR !"
110         echo " AVARICE variable is not defined, check that the script"
111         echo " is launched from a 'make fuse' in project directory"
112         exit 1
113 fi
114
115 if [ "${PROGRAMMER}" = "avarice" ]; then
116         echo "ERROR !"
117         echo " Sorry, AVARICE fuse programming is not implemented now"
118         exit 1
119 fi
120
121 if [ `wc -c ${MCU_DESC_FILE} | cut -d ' ' -f 1` -eq 0 ]; then
122         echo "Aborting : this uC does not have any fuse to program."
123         exit 0
124 fi
125
126
127 FUSE_LIST=`cut -d ' ' -f 3 ${MCU_DESC_FILE} | sort -u`
128
129 echo "Reading current fuse state"
130
131 if [ ! -z "${AVRDUDE_DELAY}" ]; then
132         DELAY="-i ${AVRDUDE_DELAY}"
133 else
134         DELAY=""
135 fi
136
137 CANNOT_READ=0
138
139 for f in ${FUSE_LIST}
140 do
141         rm -f $f 2> /dev/null
142         echo 0x00 > ${f}_new
143         ${AVRDUDE} ${DELAY} -p ${MCU} -P `echo ${AVRDUDE_PORT} | sed 's,",,g'` \
144                 -c ${AVRDUDE_PROGRAMMER} -U ${f}:r:${f}:i
145         if [ ! -f $f ]; then
146                 CANNOT_READ=1
147         fi
148 done
149
150 echo
151 echo
152
153 if [ $CANNOT_READ -eq 1 ]; then
154         echo -n "Problem during reading fuse. Continue anyway with writing ? [y/N] "
155         read ans
156         case $ans in
157                 y|Y)
158                         echo " ok"
159                         echo
160                         echo
161
162                         ;;
163                 *|n|N)
164                         echo " abort..."
165                         exit 1
166         esac
167 else
168         for f in ${FUSE_LIST}; do
169                 intel2hex $f
170                 disp_fuse $f `cat $f`
171         done
172         echo
173         echo
174 fi
175
176 echo "Now please enter the new value for each fuse. The default one"
177 echo "is the value that has been read, or factory default if read failed"
178 echo
179 echo
180
181 NB_LINE=`wc -l ${MCU_DESC_FILE} | cut -d ' ' -f 1`
182 SEQ_END=$((${NB_LINE} - 1))
183
184 for i in `seq 0 ${SEQ_END}`
185 do
186         LINE=`grep "^${i} " ${MCU_DESC_FILE}`
187         BIT=`echo ${LINE} | cut -d ' ' -f 2`
188         FUSE=`echo ${LINE} | cut -d ' ' -f 3`
189         NAME=`echo ${LINE} | cut -d ' ' -f 4`
190         FACTORY=`echo ${LINE} | cut -d ' ' -f 5`
191         DEFAULT=${FACTORY}
192         CURRENT=x
193         HELP=`echo ${LINE} | cut -d ' ' -f 6-`
194         if [ -f ${FUSE} ]; then
195                 BIN_FUSE=`cat $FUSE`
196                 bit_is_set $BIT `printf "%d" $BIN_FUSE`
197                 CURRENT=$?
198                 DEFAULT=${CURRENT}
199         fi
200
201         echo -n "[$FUSE:${BIT}] ${NAME} <${HELP}> (factory=${DEFAULT}) "
202         echo -n "(current=${CURRENT}) [${DEFAULT}] ? "
203         read ans
204
205         if [ -z "$ans" ] ; then
206                 ans=${DEFAULT}
207         fi
208
209         case $ans in
210                 1)
211                         NEW_VAL=$((1 << $BIT | `cat ${FUSE}_new`))
212                         printf "0x%x\n" ${NEW_VAL} > ${FUSE}_new
213                         # <<$ fix syntax coloration
214                         echo "    get 1 (unprogrammed)"
215                         ;;
216                 0)
217                         echo "    get 0 (programmed)"
218                         ;;
219                 *)
220                         echo "Bad answer, aborting..."
221                         exit 1
222         esac
223
224 done
225
226 echo
227 echo "Summary of new values :"
228 echo
229
230 for f in ${FUSE_LIST}; do
231         if [ ! -f ${f}_new ]; then
232                 echo "ERROR: cannot find ${f}_new, aborting"
233                 exit 1
234         fi
235         disp_fuse $f `cat ${f}_new`
236 done
237
238 echo
239
240
241 while true
242 do
243         echo -n "Are you sure ? [y/n] "
244         read ans
245
246         case $ans in
247                 y|Y)
248                         for f in ${FUSE_LIST}; do
249                                 echo "$f = $(cat ${f}_new)"
250                                 hex2intel ${f}_new
251                                 PORT=`echo ${AVRDUDE_PORT} | sed 's,",,g'`
252                                 echo -n "${AVRDUDE} -p ${MCU} -P ${PORT} "
253                                 echo -n "-c ${AVRDUDE_PROGRAMMER} "
254                                 echo "-U ${f}:w:${f}_new:i ${DELAY}"
255                                 ${AVRDUDE} -p ${MCU} -P ${PORT} \
256                                         -c ${AVRDUDE_PROGRAMMER} \
257                                         -U ${f}:w:${f}_new:i ${DELAY}
258                         done
259                         exit 0
260                         ;;
261                 n|N)
262                         echo " abort..."
263                         exit 0
264                         ;;
265                 *)
266                         echo " Please type 'y' or 'n'"
267         esac
268 done