8db50901d71407f61e405ad8393a2f13191b7809
[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 0xff > ${f}_new # default for each bit is 1 (unprogrammed)
143         ${AVRDUDE} ${DELAY} -p ${MCU} -P `echo ${AVRDUDE_PORT} | \
144                 sed 's,",,g'` -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                         echo "    get 1 (unprogrammed)"
214                         ;;
215                 0)
216                         NEW_VAL=$((~(1 << $BIT) & `cat ${FUSE}_new`))
217                         printf "0x%x\n" ${NEW_VAL} > ${FUSE}_new
218                         echo "    get 0 (programmed)"
219                         ;;
220                 *)
221                         echo "Bad answer, aborting..."
222                         exit 1
223         esac
224
225 done
226
227 echo
228 echo "Summary of new values :"
229 echo
230
231 for f in ${FUSE_LIST}; do
232         if [ ! -f ${f}_new ]; then
233                 echo "ERROR: cannot find ${f}_new, aborting"
234                 exit 1
235         fi
236         disp_fuse $f `cat ${f}_new`
237 done
238
239 echo
240
241
242 while true
243 do
244         echo -n "Are you sure ? [y/n] "
245         read ans
246
247         case $ans in
248                 y|Y)
249                         for f in ${FUSE_LIST}; do
250                                 echo "$f = $(cat ${f}_new)"
251                                 hex2intel ${f}_new
252                                 PORT=`echo ${AVRDUDE_PORT} | sed 's,",,g'`
253                                 echo -n "${AVRDUDE} -p ${MCU} -P ${PORT} "
254                                 echo -n "-c ${AVRDUDE_PROGRAMMER} "
255                                 echo "-U ${f}:w:${f}_new:i ${DELAY}"
256                                 ${AVRDUDE} -p ${MCU} -P ${PORT} \
257                                         -c ${AVRDUDE_PROGRAMMER} \
258                                         -U ${f}:w:${f}_new:i ${DELAY}
259                         done
260                         exit 0
261                         ;;
262                 n|N)
263                         echo " abort..."
264                         exit 0
265                         ;;
266                 *)
267                         echo " Please type 'y' or 'n'"
268         esac
269 done