Revision 6feb42c8

View differences:

.gitmodules
1
[submodule "Host/stm32flash"]
2
	path = Host/Source/stm32flash
3
	url = https://git.code.sf.net/p/stm32flash/code
Host/Source/SerialBoot/main.c
215 215
  printf("Copyright (c) by Feaser  http://www.feaser.com                             \n");
216 216
  printf("---------------------------------------------------------------------------\n");
217 217
  printf("This tool was modified for the 'Autonomous Mini Robot' - AMiRo.            \n");
218
  printf("Copyright (c) 2016..2017  Marvin Barther, Thomas Schoepping, and Stefan    \n");
218
  printf("Copyright (c) 2016..2018  Marvin Barther, Thomas Schoepping, and Stefan    \n");
219 219
  printf("                          Herbrechtsmeier                                  \n");
220 220
  printf("This is free software; see the source for copying conditions. There is NO  \n");
221 221
  printf("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
Host/Source/stm32flash
1
Subproject commit 1f934ae86babdeea47afdfae1d856d5fd5da6c53
README.txt
1 1
AMiRo-BLT is the bootloader and flashing toolchain for the base version of the
2
Autonomous Mini Robot (AMiRo) [1,2]. It is based on OpenBLT developed by Feaser
2
Autonomous Mini Robot (AMiRo) [1]. It is based on OpenBLT developed by Feaser
3 3
(see <http://feaser.com/en/openblt.php>).
4 4

  
5
Copyright (C) 2016..2017  Thomas Schöpping et al.
5
Copyright (C) 2016..2018  Thomas Schöpping et al.
6 6
(a complete list of all authors is given below)
7 7

  
8 8
This program is free software: you can redistribute it and/or modify
......
24 24

  
25 25
Authors:
26 26
 - Thomas Schöpping        <tschoepp[at]cit-ec.uni-bielefeld.de>
27
 - Stefan Herbechtsmeier   <sherbrec[at]cit-ec.uni-bielefeld.de>
27
 - Stefan Herbrechtsmeier  <sherbrec[at]cit-ec.uni-bielefeld.de>
28 28
 - Marvin Barther
29 29

  
30 30
References:
31
 [1] Herbrechtsmeier S., Rückert U., & Sitte J. (2012). "AMiRo - Autonomous Mini
32
     Robot for Research and Education". In Advances in Autonomous Mini Robots
33
     (pp. 101-112). Springer Berlin Heidelberg.
34
 [2] Schöpping T., Korthals T., Herbrechtsmeier S., & Rückert U. (2015). "AMiRo:
35
     A Mini Robot for Scientific Applications" In Advances in Computational
36
     Intelligence (pp. 199-205). Springer International Publishing.
37
 
31
 [1] S. Herbrechtsmeier, T. Korthals, T. Schopping and U. Rückert, "AMiRo: A
32
     modular & customizable open-source mini robot platform," 2016 20th
33
     International Conference on System Theory, Control and Computing (ICSTCC),
34
     Sinaia, 2016, pp. 687-692.
35

  
38 36

  
39 37

  
40 38
################################################################################
......
58 56
CONTENTS:
59 57

  
60 58
  1  Required software
61
    1.1  stm32flash
62
    1.2  GCC ARM Embedded Toolchain
63
    1.3  GNU Make
64
    1.4  CMake
59
    1.1  Git
60
    1.2  GNU Make
61
    1.3  GCC
62
    1.4  stm32flash
63
    1.5  GCC ARM Embedded Toolchain
64
    1.6  CMake
65 65
  2  Recommended Software
66 66
  3  Compiling the source code
67
    3.1  target software
68
    3.2  host software
67
    3.1  host software
68
    3.2  target software
69 69

  
70 70
================================================================================
71 71

  
......
80 80
to the hardware.
81 81

  
82 82

  
83
1.1 - Git
84
---------
85

  
86
Since all main- and subprojects are available as Git repositories, installing a
87
recent version of the tool is mandatory.
88

  
89

  
90
1.2 - GNU Make
91
--------------
92

  
93
GNU Make usually comes as preinstalled tool on Ubuntu based operating systems.
94
If your system is missing GNU Make, it is recommended to install it from the
95
standard repositories since no special requirements (e.g. features of a very
96
recent version) are required.
97

  
83 98

  
84
1.1 - stm32flash
99
1.3 - GCC
100
---------
101

  
102
In order to build some required tools from source, GCC is required. It usually
103
comes as preinstalled tool on Ubuntu based operating systems. If your system is
104
missing GCC, it is recommended to install it from the standard repositories
105
since no special requirements (e.g. features of a very recent version) are
106
required.
107

  
108

  
109
1.4 - stm32flash
85 110
----------------
86 111

  
87
To build the tool from source, clone the GIT repository to a local folder on
88
your machine:
89
  >$ git clone git://git.code.sf.net/p/stm32flash/code
90
Make sure that you have selected version 0.4 or later of the tool. You can now
91
build the tool simply by executing 'make'. Finally, you must make the resulting
92
binary (stm32flash) globally available in your environment. You can do so by
93
either copying the file to an appropriate location (e.g. /usr/local/bin/) or
94
creating an according link. The tool must be available as 'stm32flash' in every
95
new shell.
112
This tool is required to flash the bootloader binaries to the microcontrollers.
113
Since it is included in this project as a submodule, you can just run the setup
114
script in the root directory:
115
  >$ ./setup.sh
116
Follow the instructions to download the source code and compile the tool. The
117
resulting binary path is ./Host/Source/stm32flash/stm32flash. Other scripts that
118
require stm32flash will search for the binary at this location by default.
96 119

  
120
The setup script does not install the tool to your system path, though, since
121
this usually requires root permissions. However, stm32flash provides a Makefile
122
with installation capabilities. Just Follow the instructions given in the file
123
./Host/Source/stm32flash/INSTALL.
97 124

  
98
1.2 - GCC ARM Embedded Toolchain
125

  
126
1.5 - GCC ARM Embedded Toolchain
99 127
--------------------------------
100 128

  
101 129
Various versions of the GCC for ARM embedded devices can be found at
102 130
<https://launchpad.net/gcc-arm-embedded>. For installation of the compiler
103
toolchain, please follow the instructions that can be found on the web page.
104
If you have access to the AMiRo-OS project as well, it is highly recommended
105
to use the setup application provided there.
106

  
131
toolchain and managing of multiple versions, it is highly recommended to use the
132
provided setup script. Alternatively you can install the compiler manually by
133
following the instructions that can be found on the web page.
107 134

  
108
1.3 - GNU Make
109
--------------
110

  
111
GNU Make usually comes as preinstalled tool on Ubuntu based operating systems.
112
If your system is missing GNU Make, it is recommended to install it from the
113
standard repositories since no special requirements (e.g. features of a very
114
recent version) are required.
135
If you are running a 64-bit operating system, you may have to install several
136
32-bit libraries in order to make the compiler work. The required packages are
137
libc6, libstdc++6, and libncurses5. You can run the following shell commands to
138
install the according 32-bit versions of the packages:
139
  >$ sudo dpkg --add-architecture i386 && sudo apt-get update
140
  >$ sudo apt-get install libc6:i386 libstdc++6:i386 libncurses5:i386
115 141

  
116 142

  
117
1.4 - CMake
143
1.6 - CMake
118 144
-----------
119 145

  
120 146
In order to build the SerialBoot host application, CMake version 2.8 or later is
......
146 172
even for other modules.
147 173

  
148 174

  
149
3.1 - target software
175
3.1 - host software
176
-------------------
177

  
178
The stm32flash tool is requried to flash bootloader binaries to the MCUs.
179
Instructions for builing the tool are given in chapter 1.4 of this file.
180

  
181
The SerialBoot tool can be built by using cmake. The according CMakeLists.txt
182
file can be found in the ./Host/Source/SerialBoot/ directory. To ensure
183
compatibility with other software (e.g. AMiRo-OS) it is higly recommended to use
184
the provided ./setup.sh script to build SerialBoot. In the end the binary path
185
should be ./Host/Source/SerialBoot/build/SerialBoot, which is the default for
186
any scripts and tools that use SerialBoot.
187

  
188

  
189
3.2 - target software
150 190
---------------------
151 191

  
152 192
In the ./Target/Demo/ directory there are three subfolders, one for each AMiRo
......
155 195
be compiled by executing 'make' in these directories.
156 196

  
157 197
In order to flash the bootloader to a microcontroller, you first have to set
158
full read and write permissions to the USB ports of your system. You can do so
159
by executing the following command:
160
  >$ sudo echo 'KERNEL=="ttyUSB[0-9]*",NAME="tts/USB%n",SYMLINK+="%k",MODE="0666"' > /etc/udev/rules.d/50-ttyusb.rules
198
full read and write permissions to the USB ports of your system. To do so, first
199
create a new file by executing the following command:
200
  >$ sudo touch /etc/udev/rules.d/50-usb-serial.rules
201
Open the file in a text editor of your choice (sudo required) and add the
202
following lines:
203

  
204
  # Future Technology Devices International Ltd. - TTL-232RG
205
  SUBSYSTEMS=="usb", ACTION=="add", KERNEL=="ttyUSB[0-9]*",
206
  ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", MODE="0666"
207

  
208
  # Future Technology Devices International Ltd. - FT231X
209
  SUBSYSTEMS=="usb", ACTION=="add", KERNEL=="ttyUSB[0-9]*",
210
  ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6015", MODE="0666"
211

  
161 212
Now connect the module you want to flash directly to your system (note that
162 213
indirect flashing is not possible for the bootloader itself) and run the command
163 214
  >$ make flash
164 215
If the procedure was not successful, the following hints might help:
216
  - Did your system apply the new udev rules?
217
    Reboot and try again!
165 218
  - Could the makefile execute the stm32flash tool?
219
    Reinitialize the submodule and try again!
166 220
  - Are the permissions for USB ports set correctly?
221
    Check the udev rules!
167 222
  - Are there any other applications using the serial connection?
223
    Close any other applications using the serial connection!
168 224
  - Is the AMiRo module connected to your system?
225
    Use the programming cable to connect the module to your system.
169 226
  - Is the AMiRo module powered up?
227
    Keep a charger plugged in during flashing.
170 228

  
171 229
ATTENTION:
172 230
Never flash a bootloader to the wrong module! Doing so might cause severe errors
173 231
and damage the robot.
174 232

  
175

  
176
3.2 - host software
177
-------------------
178

  
179
The SerialBoot tool can be built by using cmake. The according CMakeLists.txt
180
file can be found in the ./Host/Source/SerialBoot/ directory. To ensure
181
compatibility with other software (e.g. AMiRo-OS) it is higly recommended to use
182
the provided ./setup.sh script to build SerialBoot. In the end the binary path
183
should be ./Host/Sotware/SerialBoot/build/SerialBoot.
184

  
185 233
================================================================================
186 234

  
Target/Demo/ARMCM3_STM32F103_DiWheelDrive_GCC/Boot/main.c
170 170

  
171 171
const blCallbackTable_t cbtable __attribute__ ((section ("_callback_table"))) = {
172 172
  .magicNumber = BL_MAGIC_NUMBER,
173
  .vBootloader = {BL_VERSION_ID_AMiRoBLT_Release, BL_VERSION_MAJOR, BL_VERSION_MINOR, 0},
173
  .vBootloader = {BL_VERSION_ID_AMiRoBLT_Release, BL_VERSION_MAJOR, BL_VERSION_MINOR, 1},
174 174
  .vSSSP = {BL_VERSION_ID_SSSP, SSSP_VERSION_MAJOR, SSSP_VERSION_MINOR, 0},
175 175
  .vCompiler = {BL_VERSION_ID_GCC, __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__},  // currently only GCC is supported
176 176
  .cbShutdownHibernate = blCallbackShutdownHibernate,
Target/Demo/ARMCM3_STM32F103_LightRing_GCC/Boot/main.c
140 140

  
141 141
const blCallbackTable_t cbtable __attribute__ ((section ("_callback_table"))) = {
142 142
  .magicNumber = BL_MAGIC_NUMBER,
143
  .vBootloader = {BL_VERSION_ID_AMiRoBLT_Release, BL_VERSION_MAJOR, BL_VERSION_MINOR, 0},
143
  .vBootloader = {BL_VERSION_ID_AMiRoBLT_Release, BL_VERSION_MAJOR, BL_VERSION_MINOR, 1},
144 144
  .vSSSP = {BL_VERSION_ID_SSSP, SSSP_VERSION_MAJOR, SSSP_VERSION_MINOR, 0},
145 145
  .vCompiler = {BL_VERSION_ID_GCC, __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__},  // currently only GCC is supported
146 146
  .cbShutdownHibernate = blCallbackShutdownHibernate,
Target/Demo/ARMCM4_STM32F405_Power_Management_GCC/Boot/main.c
193 193

  
194 194
const blCallbackTable_t cbtable __attribute__ ((section ("_callback_table"))) = {
195 195
  .magicNumber = BL_MAGIC_NUMBER,
196
  .vBootloader = {BL_VERSION_ID_AMiRoBLT_Release, BL_VERSION_MAJOR, BL_VERSION_MINOR, 0},
196
  .vBootloader = {BL_VERSION_ID_AMiRoBLT_Release, BL_VERSION_MAJOR, BL_VERSION_MINOR, 1},
197 197
  .vSSSP = {BL_VERSION_ID_SSSP, SSSP_VERSION_MAJOR, SSSP_VERSION_MINOR, 0},
198 198
  .vCompiler = {BL_VERSION_ID_GCC, __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__},  // currently only GCC is supported
199 199
  .cbShutdownHibernate = blCallbackShutdownHibernate,
Target/Demo/flash.mk
1
STM32FLASH = stm32flash
1
STM32FLASH := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))../../Host/Source/stm32flash/stm32flash
2 2
ifeq ($(OS),Windows_NT)
3 3
	STM32FLASH_PORT ?= COM5
4 4
else
Target/Makefile
1
################################################################################
2
# AMiRo-BLT is the bootloader and flashing toolchain for the base version of   #
3
# the Autonomous Mini Robot (AMiRo). It is based on OpenBLT developed by       #
4
# Feaser (see <http://feaser.com/en/openblt.php>).                             #
5
# Copyright (C) 2016..2018  Thomas Schöpping et al.                            #
6
#                                                                              #
7
# This program is free software: you can redistribute it and/or modify         #
8
# it under the terms of the GNU General Public License as published by         #
9
# the Free Software Foundation, either version 3 of the License, or            #
10
# (at your option) any later version.                                          #
11
#                                                                              #
12
# This program is distributed in the hope that it will be useful,              #
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of               #
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the                 #
15
# GNU General Public License for more details.                                 #
16
#                                                                              #
17
# You should have received a copy of the GNU General Public License            #
18
# along with this program.  If not, see <http://www.gnu.org/licenses/>.        #
19
#                                                                              #
20
# This research/work was supported by the Cluster of Excellence Cognitive      #
21
# Interaction Technology 'CITEC' (EXC 277) at Bielefeld University, which is   #
22
# funded by the German Research Foundation (DFG).                              #
23
################################################################################
24

  
25

  
26

  
27
ROOT_PATH = ..
28
DWD_PATH = $(ROOT_PATH)/Target/Demo/ARMCM3_STM32F103_DiWheelDrive_GCC/Boot
29
PM_PATH = $(ROOT_PATH)/Target/Demo/ARMCM4_STM32F405_Power_Management_GCC/Boot
30
LR_PATH = $(ROOT_PATH)/Target/Demo/ARMCM3_STM32F103_LightRing_GCC/Boot
31

  
32
all:
33
	$(MAKE) -C $(DWD_PATH)
34
	$(MAKE) -C $(PM_PATH)
35
	$(MAKE) -C $(LR_PATH)
36

  
37
clean:
38
	$(MAKE) -C $(DWD_PATH) clean
39
	$(MAKE) -C $(PM_PATH) clean
40
	$(MAKE) -C $(LR_PATH) clean
41

  
42
DiWheelDrive:
43
	$(MAKE) -C $(DWD_PATH)
44

  
45
PowerManagement:
46
	$(MAKE) -C $(PM_PATH)
47

  
48
LightRing:
49
	$(MAKE) -C $(LR_PATH)
50

  
51
flash_DiWheelDrive:
52
	$(MAKE) -C $(DWD_PATH) flash
53

  
54
flash_PowerManagement:
55
	$(MAKE) -C $(PM_PATH) flash
56

  
57
flash_LightRing:
58
	$(MAKE) -C $(LR_PATH) flash
59

  
compiler/GCC/gccsetup.sh
1
################################################################################
2
# AMiRo-BLT is an bootloader and toolchain designed for the Autonomous Mini    #
3
# Robot (AMiRo) platform.                                                      #
4
# Copyright (C) 2016..2018  Thomas Schöpping et al.                            #
5
#                                                                              #
6
# This program is free software: you can redistribute it and/or modify         #
7
# it under the terms of the GNU General Public License as published by         #
8
# the Free Software Foundation, either version 3 of the License, or            #
9
# (at your option) any later version.                                          #
10
#                                                                              #
11
# This program is distributed in the hope that it will be useful,              #
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of               #
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                #
14
# GNU General Public License for more details.                                 #
15
#                                                                              #
16
# You should have received a copy of the GNU General Public License            #
17
# along with this program.  If not, see <http://www.gnu.org/licenses/>.        #
18
#                                                                              #
19
# This research/work was supported by the Cluster of Excellence Cognitive      #
20
# Interaction Technology 'CITEC' (EXC 277) at Bielefeld University, which is   #
21
# funded by the German Research Foundation (DFG).                              #
22
################################################################################
23

  
24
#!/bin/bash
25

  
26
################################################################################
27
# GENERIC FUNCTIONS                                                            #
28
################################################################################
29

  
30
### print an error message #####################################################
31
# Prints a error <message> to standard output.
32
#If variable 'LOG_FILE' is specified, the message is also appended to the given file.
33
#
34
# usage:      printError <message>
35
# arguments:  <message>
36
#                 Message string to print.
37
# return:     n/a
38
#
39
function printError {
40
  local string="ERROR:   $1"
41
  # if a log file is specified
42
  if [ -n "$LOG_FILE" ]; then
43
    printf "[$(date '+%Y-%m-%d %H:%M:%S')] $string" >> $LOG_FILE
44
  fi
45
  printf "$(tput setaf 1)>>> $string$(tput sgr 0)" 1>&2
46
}
47

  
48
### print a warning message ####################################################
49
# Prints a warning <message> to standard output.
50
#If variable 'LOG_FILE' is specified, the message is also appended to the given file.
51
#
52
# usage:      printMessage <message>
53
# arguments:  <message>
54
#                 Message string to print.
55
# return:     n/a
56
#
57
function printWarning {
58
  local string="WARNING: $1"
59
  # if a log file is specified
60
  if [ -n "$LOG_FILE" ]; then
61
    printf "[$(date '+%Y-%m-%d %H:%M:%S')] $string" >> $LOG_FILE
62
  fi
63
  printf "$(tput setaf 3)>>> $string$(tput sgr 0)"
64
}
65

  
66
### print an information message ###############################################
67
# Prints an information <message> to standard output.
68
#If variable 'LOG_FILE' is specified, the message is also appended to the given file.
69
#
70
# usage:      printInfo <message>
71
# arguments:  <message>
72
#                 Message string to print.
73
# return:     n/a
74
#
75
function printInfo {
76
  local string="INFO:    $1"
77
  # if a log file is specified
78
  if [ -n "$LOG_FILE" ]; then
79
    printf "[$(date '+%Y-%m-%d %H:%M:%S')] $string" >> $LOG_FILE
80
  fi
81
  printf "$(tput setaf 2)>>> $string$(tput sgr 0)"
82
}
83

  
84
### print a message to file ####################################################
85
# Appends a <message> to a log file, specified by the variable 'LOG_FILE'.
86
#
87
# usage       printLog <message>
88
# arguments:  <message>
89
#                 Message string to print.
90
# return:     n/a
91
#
92
function printLog {
93
  local string="LOG:     $1"
94
  # if a log file is specified
95
  if [ -n "$LOG_FILE" ]; then
96
    printf "[$(date '+%Y-%m-%d %H:%M:%S')] $string" >> $LOG_FILE
97
  fi
98
}
99

  
100
### exit the script normally ###################################################
101
# Prints a delimiter and exits the script normally (returns 0).
102
#
103
# usage:      quitScript
104
# arguments:  n/a
105
# return:     0
106
#                 No error or warning occurred.
107
#
108
function quitScript {
109
  printInfo "exiting $(realpath ${BASH_SOURCE[0]})\n"
110
  printf "\n"
111
  printf "######################################################################\n"
112
  exit 0
113
}
114

  
115
### read a user input ##########################################################
116
# Reads a single character user input from a set up <options> and stores it in
117
# a given <return> variable.
118
#
119
# usage:      readUserInput <options> <return>
120
# arguments:  <options>
121
#                 String definiing the set of valid characters.
122
#                 If the string is empty, the user can input any character.
123
#             <return>
124
#                 Variable to store the selected character to.
125
# return:     n/a
126
#
127
function readUserInput {
128
  local input=""
129
  # read user input
130
  while [ -z $input ] || ( [ -n "$1" ] && [[ ! $input =~ ^[$1]$ ]] ); do
131
    read -p "your selection: " -n 1 -e input
132
    if [ -z $input ] || ( [ -n "$1" ] && [[ ! $input =~ ^[$1]$ ]] ); then
133
      printWarning "[$input] is no valid action\n"
134
    fi
135
  done
136
  printLog "[$input] has been selected\n"
137
  eval $2="$input"
138
}
139

  
140
### check whether argument is an option ########################################
141
# Checks a <string> whether it is an option.
142
# Options are defined to either start with '--' followed by any string, or
143
# to start with a single '-' followed by a single character, or
144
# to start with a single '-' followed by a single character, a '=' and any string.
145
# Examples: '--option', '--option=arg', '-o', '-o=arg', '--'
146
#
147
# usage:      parseIsOption <string>
148
# arguments:  <string>
149
#                 A string to check whether it is an option.
150
# return:     0
151
#                 <string> is an option.
152
#             -1
153
#                 <string> is not an option.
154
#
155
function parseIsOption {
156
  if [[ "$1" =~ ^-(.$|.=.*) ]] || [[ "$1" =~ ^--.* ]]; then
157
    return 0
158
  else
159
    return -1
160
  fi
161
}
162

  
163
### set the log file ###########################################################
164
# Sets a specified <infile> as log file and checks whether it already exists.
165
# If so, the log may either be appended to the file, its content can be cleared,
166
# or no log is generated at all.
167
# The resulting path is stored in <outvar>.
168
#
169
# usage:      setLogFile [--option=<option>] [--quiet] <infile> <outvar>
170
# arguments:  --option=<option>
171
#                 Select what to do if <file> already exists.
172
#                 Possible values are 'a', 'c', 'r' and 'n'.
173
#                 - a: append (starts with a separator)
174
#                 - c: continue (does not insert a seperator)
175
#                 - r: delete and restart
176
#                 - n: no log
177
#                 If no option is secified but <file> exists, an interactive selection is provided.
178
#             --quiet
179
#                 Suppress all messages.
180
#             <infile>
181
#                 Path of the wanted log file.
182
#             <outvar>
183
#                 Variable to store the path of the log file to.
184
# return:     0
185
#                 No error or warning occurred.
186
#             -1
187
#                 Error: invalid input
188
#
189
function setLogFile {
190
  local filepath=""
191
  local option=""
192
  local quiet=false
193

  
194
  # parse arguments
195
  local otherargs=()
196
  while [ $# -gt 0 ]; do
197
    if ( parseIsOption $1 ); then
198
      case "$1" in
199
        -o=*|--option=*)
200
          option=${1#*=}; shift 1;;
201
        -o*|--option*)
202
          option="$2"; shift 2;;
203
        -q|--quiet)
204
          quiet=true; shift 1;;
205
        *)
206
          printError "invalid option: $1\n"; shift 1;;
207
      esac
208
    else
209
      otherargs+=("$1")
210
      shift 1
211
    fi
212
  done
213
  filepath=$(realpath ${otherargs[0]})
214

  
215
  # if file already exists
216
  if [ -e $filepath ]; then
217
    # if no option was specified, ask what to do
218
    if [ -z "$option" ]; then
219
      printWarning "log file $filepath already esists\n"
220
      local userinput=""
221
      printf "Select what to do:\n"
222
      printf "  [A] - append log\n"
223
      printf "  [R] - restart log (delete existing file)\n"
224
      printf "  [N] - no log\n"
225
      readUserInput "AaRrNn" userinput
226
      option=${userinput,,}
227
    fi
228
    # evaluate option
229
    case "$option" in
230
      a|c)
231
        if [ $quiet = false ]; then
232
          printInfo "appending log to $filepath\n"
233
        fi
234
        if [ $option != c ]; then
235
          printf "\n" >> $filepath
236
          printf "######################################################################\n" >> $filepath
237
          printf "\n" >> $filepath
238
        fi
239
        ;;
240
      r)
241
        echo -n "" > $filepath
242
        if [ $quiet = false ]; then
243
          printInfo "content of $filepath wiped\n"
244
        fi
245
        ;;
246
      n)
247
        if [ $quiet = false ]; then
248
          printInfo "no log file will be generated\n"
249
        fi
250
        filepath=""
251
        ;;
252
      *) # sanity check (return error)
253
        printError "unexpected argument: $option\n"; return -1;;
254
    esac
255
  else
256
    if [ $quiet = false ]; then
257
      printInfo "log file set to $filepath\n"
258
    fi
259
  fi
260

  
261
  eval ${otherargs[1]}="$filepath"
262

  
263
  return 0
264
}
265

  
266
################################################################################
267
# SPECIFIC FUNCTIONS                                                           #
268
################################################################################
269

  
270
### print welcome text #########################################################
271
# Prints a welcome message to standard out.
272
#
273
# usage:      printWelcomeText
274
# arguments:  n/a
275
# return:     n/a
276
#
277
function printWelcomeText {
278
  printf "######################################################################\n"
279
  printf "#                                                                    #\n"
280
  printf "#                     Welcome to the GCC setup!                      #\n"
281
  printf "#                                                                    #\n"
282
  printf "######################################################################\n"
283
  printf "#                                                                    #\n"
284
  printf "# Copyright (c) 2016..2018  Thomas Schöpping                         #\n"
285
  printf "#                                                                    #\n"
286
  printf "# This is free software; see the source for copying conditions.      #\n"
287
  printf "# There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR  #\n"
288
  printf "# A PARTICULAR PURPOSE. The development of this software was         #\n"
289
  printf "# supported by the Excellence Cluster EXC 227 Cognitive Interaction  #\n"
290
  printf "# Technology. The Excellence Cluster EXC 227 is a grant of the       #\n"
291
  printf "# Deutsche Forschungsgemeinschaft (DFG) in the context of the German #\n"
292
  printf "# Excellence Initiative.                                             #\n"
293
  printf "#                                                                    #\n"
294
  printf "######################################################################\n"
295
}
296

  
297
### print help #################################################################
298
# Prints a help text to standard out.
299
#
300
# usage:      printHelp
301
# arguments:  n/a
302
# return:     n/a
303
#
304
function printHelp {
305
  printInfo "printing help text\n"
306
  printf "usage:    $(basename ${BASH_SOURCE[0]}) [-h|--help] [-i|--install] [-c|--change] [-q|--quit] [--log=<file>]\n"
307
  printf "\n"
308
  printf "options:  -h, --help\n"
309
  printf "              Print this help text.\n"
310
  printf "          -i, --install\n"
311
  printf "              Install another version.\n"
312
  printf "          -u, --uninstall\n"
313
  printf "              Unistall a version.\n"
314
  printf "          -c, --change\n"
315
  printf "              Change the default version.\n"
316
  printf "          -q, --quit\n"
317
  printf "              Quit the script.\n"
318
  printf "          --log=<file>\n"
319
  printf "              Specify a log file.\n"
320
}
321

  
322
### detect installed versions ##################################################
323
# Detect all installed version of arm-none-eabi-gcc, if any.
324
#
325
# usage:      detectInstalledVersions <binarray> <current> [<current_idx>]
326
# arguments:  <binarray>
327
#                 Array variable to store all detected binary paths to. 
328
#             <current>
329
#                 Variable to store the currently active binary to.
330
#             <current_idx>
331
#                 Index of the curretly selected version in the output array (<binarray>).
332
# return:     n/a
333
#
334
function detectInstalledVersions {
335
  local armgcc_command=$(command -v arm-none-eabi-gcc)
336
  local armgcc_commanddir=${HOME}/gcc-none-eabi
337
  local armgcc_currentbin=""
338
  local armgcc_installdir=${HOME}/gcc-none-eabi
339
  local armgcc_bins=()
340
  local armgcc_bincnt=0
341

  
342
  # check for already installed versions
343
  if [ -n "$armgcc_command" ]; then
344
    # follow the link to the actual binary
345
    armgcc_commanddir=$(dirname $armgcc_command)
346
    armgcc_currentbin=$armgcc_command
347
    while [ -L $armgcc_currentbin ]; do
348
      # differentiate between relative and absolute paths
349
      if [[ $(readlink $armgcc_currentbin) = /* ]]; then
350
        armgcc_currentbin=$(readlink $armgcc_currentbin)
351
      else
352
        armgcc_currentbin=$(realpath $(dirname $armgcc_currentbin)/$(readlink $armgcc_currentbin))
353
      fi
354
    done
355
    # the installation location is assumed to be two directories up
356
    armgcc_installdir=$(realpath $(dirname ${armgcc_currentbin})/../..)
357
    # list all detected instalations
358
    for dir in $(ls -d ${armgcc_installdir}/*/); do
359
      if [ -f ${dir}/bin/arm-none-eabi-gcc ]; then
360
        armgcc_bins[$armgcc_bincnt]=${dir}bin/arm-none-eabi-gcc
361
        armgcc_bincnt=$((armgcc_bincnt + 1))
362
      fi
363
    done
364

  
365
    # set the output variables
366
    eval "$1=(${armgcc_bins[*]})"
367
    eval $2="$armgcc_currentbin"
368
    if [ -n "$3" ]; then
369
      for (( bin=0; bin<${#armgcc_bins[@]}; ++bin )); do
370
        if [ ${armgcc_bins[bin]} = "$armgcc_currentbin" ]; then
371
          eval $3=$bin
372
        fi
373
      done
374
    fi
375
  else
376
    eval "$1=()"
377
    eval $2=""
378
    if [ -n "$3" ]; then
379
      eval $3=""
380
    fi
381
  fi
382
}
383

  
384
### install new version ########################################################
385
# Fetches an installation package from the internet, installs it and expands
386
# the $PATH environment variable (via .bashrc) if required.
387
#
388
# usage:      installNewVersion [-i|--install=<path>] [-l|--link=<path>]
389
# argumenst:  -i, --install <path>
390
#                 Path where to install the new version to.
391
#             -l, --link <path>
392
#                 Path where to create according links.
393
# return:     0
394
#                 No error or warnign occurred.
395
#             1
396
#                 Warning: Installation aborted by user.
397
#
398
function installNewVersion {
399
  local installbasedir=${HOME}/gcc-arm-embedded
400
  local linkdir="/usr/bin"
401

  
402
  # parse arguments
403
  local otherargs=()
404
  while [ $# -gt 0 ]; do
405
    if ( parseIsOption $1 ); then
406
      case "$1" in
407
        -i=*|--install=*)
408
          installbasedir=$(realpath "${1#*=}"); shift 1;;
409
        -i|--install)
410
          installbasedir="$2"; shift 2;;
411
        -l=*|--link=*)
412
          linkdir=$(realpath "${1#*=}"); shift 1;;
413
        -l|--link)
414
          linkdir="$2"; shift 2;;
415
        *) # sanity check (exit with error)
416
          printError "invalid option: $1\n"; shift 1;;
417
      esac
418
    else
419
      otherargs+=("$1")
420
      shift 1
421
    fi
422
  done
423

  
424
  # read download URL form user
425
  printLog "read installation url from user\n"
426
  local armgcc_downloadurl=""
427
  while [ -z "$armgcc_downloadurl" ]; do
428
    read -p "Download link for the installation file: " -e armgcc_downloadurl
429
    if [ -z "$armgcc_downloadurl" ]; then
430
      printWarning "installation aborted by user\n"
431
      return 1
432
    fi
433
    if [[ $armgcc_downloadurl != *".tar.bz2" ]]; then
434
      printWarning "please specify a .tar.bz2 file\n"
435
      armgcc_downloadurl=""
436
    fi
437
    if [ ! wget --spider $armgcc_downloadurl 2>/dev/null ]; then
438
      printWarning "$armgcc_downloadurl can not be reached\n"
439
      armgcc_downloadurl=""
440
    fi
441
  done
442
  printLog "user selected $armgcc_downloadurl\n"
443

  
444
  # if the file already exists, ask the user if it should be downloaded again
445
  local armgcc_tarball=$(basename "$armgcc_downloadurl")
446
  if [ -e "$armgcc_tarball" ]; then
447
    printWarning "$armgcc_tarball already exists. Delete and redownload? [y/n]\n"
448
    local userinput=""
449
    readUserInput "YyNn" userinput
450
    case "$userinput" in
451
      Y|y)
452
        rm "$armgcc_tarball"
453
        wget "$armgcc_downloadurl" | tee -a $LOG_FILE
454
        ;;
455
      N|n)
456
        ;;
457
      *) # sanity check (exit with error)
458
        printError "unexpected argument: $userinput\n";;
459
    esac
460
  else
461
    wget "$armgcc_downloadurl" | tee -a $LOG_FILE
462
  fi
463

  
464
  # extract tarball
465
  printInfo "extracting ${armgcc_tarball}...\n"
466
  tar -jxf "$armgcc_tarball" | tee -a $LOG_FILE
467
  local compilerdir=`tar --bzip2 -tf ${armgcc_tarball} | sed -e 's@/.*@@' | uniq`
468

  
469
  # install gcc arm embedded
470
  printLog "read installation directory from user\n"
471
  local installdir=""
472
  read -p "Installation directory: " -i ${installbasedir}/${compilerdir} -e installdir
473
  printLog "user selected $installdir\n"
474
  printLog "read link directory\n"
475
  read -p "Link directory: " -i $linkdir -e linkdir
476
  printLog "user selected $linkdir\n"
477
  # if the installation path already exists, ask user to overwrite
478
  if [ -d "$installdir" ]; then
479
    printWarning "$installdir already exists. Overwrite? [y/n]\n"
480
    local userinput=""
481
    readUserInput "YyNn" userinput
482
    case "$userinput" in
483
      Y|y)
484
        ;;
485
      N|n)
486
        printWarning "installation aborted by user\n"
487
        return 1
488
        ;;
489
      *) # sanity check (exit with error)
490
        printError "invalid option: $userinput\n";;
491
    esac
492
  # make sure the whole ínstallation path exists
493
  else
494
    while [ ! -d $(dirname "$installdir") ]; do
495
      local dir=$(dirname "$installdir") 
496
      while [ ! -d $(dirname "$dir") ]; do
497
        dir=$(dirname "$dir")
498
      done
499
      echo "mkdir $dir"
500
      mkdir "$dir"
501
    done
502
  fi
503
  # copy the extracted compiler folder
504
  cp -fR "$compilerdir" "$installdir"
505
  # make sure whole link path exists
506
  while [ ! -d "$linkdir" ]; do
507
    local dir="$linkdir"
508
    while [ ! -d $(dirname "$linkdir") ]; do
509
      dir=$(dirname "$dir")
510
    done
511
    mkdir "$dir"
512
  done
513
  # create / overwrite links
514
  ls ${installdir}/bin/ | xargs -i ln -sf ${installdir}/bin/{} ${linkdir}/{}
515
  printInfo "default version set to $(arm-none-eabi-gcc -dumpversion)\n"
516

  
517
  # append the link directory to the PATH environment variable if required
518
  if [[ ! "$linkdir" = *"$PATH"* ]]; then
519
    local bashrc_file=${HOME}/.bashrc
520
    local bashrc_identifier="##### AMiRo ENVIRONMENT CONFIGURATION #####"
521
    local bashrc_note="# DO NOT EDIT THESE LINES MANUALLY!"
522
    local bashrc_entry="export PATH=\$PATH:$linkdir"
523

  
524
    # find and edit old entry, or append a new one to the file
525
    local bashrc_idlines=$(grep -x -n "$bashrc_identifier" "$bashrc_file" | cut -f1 -d:) # string of line numbers
526
    bashrc_idlines=(${bashrc_idlines//"\n"/" "}) # array of line numbers
527
    case ${#bashrc_idlines[@]} in
528

  
529
      # append a new entry to the BASHRC_FILE
530
      0)
531
        # make sure the last line is empty
532
        if [[ ! $(tail -1 $bashrc_file) =~ ^[\ \t]*$ ]]; then
533
          printf "\n" >> $bashrc_file
534
        fi
535
        # append text to file
536
        sed -i '$a'"$bashrc_identifier\n$bashrc_note\n$bashrc_entry\n$bashrc_identifier\n" $bashrc_file
537
        # print note
538
        printInfo "Your $bashrc_file has been updated. You need to source it to apply the changes in your environment.\n"
539
        read -p "  Understood!"
540
        ;;
541

  
542
      # extend the old entry
543
      2)
544
        # don't do anything if the line is already present
545
        local bashrc_entrylines=$(grep -x -n "$bashrc_entry" $bashrc_file | cut -f1 -d:) # string of line numbers
546
        bashrc_entrylines=(${bashrc_entrylines//"\n"/" "}) # array of line numbers
547
        if [[ ${#bashrc_entrylines[@]} = 0 ]]; then
548
          # insert the entry before the closing identifier
549
          sed -i "${bashrc_idlines[1]}"'i'"$bashrc_entry" $bashrc_file
550
          # print note
551
          printInfo "Your $bashrc_file has been updated. You need to source it to apply the changes in your environment.\n"
552
          read -p "  Understood!"
553
        elif [[ ${#bashrc_entrylines[@]} -eq 1 && ( ${bashrc_entrylines[0]} -lt ${bashrc_idlines[0]} || ${bashrc_entrylines[0]} -gt ${bashrc_idlines[1]} ) ]]; then
554
          # print an error that there is an entry at the wrong place
555
          printError "corrupted entry in your $bashrc_file detected\n"
556
          printf "The following entry was found at the wrong place:\n"
557
          printf "\n"
558
          printf "$bashrc_entry\n"
559
          printf "\n"
560
          printf "To fix this, delete the line and rerun this setup.\n"
561
          read -p "  Understood!"
562
        elif [[ ${#bashrc_entrylines[@]} -gt 1 ]]; then
563
          # print an error that there are multiple entries
564
          printError "corrupted entry in your $bashrc_file detected\n"
565
          printf "There are multiple identical entries in your $bashrc_file file.\n"
566
          printf "To fix it, make sure that it contains the following line exactly once:\n"
567
          printf "\n"
568
          printf "$bashrc_entry\n"
569
          printf "\n"
570
          read -p "  Understood!"
571
        fi
572
        ;;
573

  
574
      # error state (corrupted entry detected)
575
      *)
576
        printError "unable to append link directory to \$PATH variable\n"
577
        printf "There seems to be a broken entry in your $bashrc_file file.\n"
578
        printf "To fix it, make sure that the following line appears exactly twice and encloses your AMiRo related settings:\n"
579
        printf "\n"
580
        printf "$bashrc_identifier\n"
581
        printf "\n"
582
        read -p "  Understood!"
583
        ;;
584
    esac
585
  fi
586

  
587
  # clean up the current directory
588
  rm "$armgcc_tarball"
589
  rm -rf "$compilerdir"
590

  
591
  return 0
592
}
593

  
594
### uninstall a version ########################################################
595
# Select an installed version and uninstall it from the system.
596
#
597
# usage:      uninstallVersion <versions> <current_idx> <linkdir>
598
# arguments:  <version>
599
#                 Array of available versions (full path to binary).
600
#             <current_idx>
601
#                 Index of the currently selected version in the array.
602
#             <linkdir>
603
#                 Path where to delete old links.
604
# return:     0
605
#                 No error or warning occurred.
606
#             1
607
#                 Warning: Installation aborted by user.
608
#             -1
609
#                 Error: An exception occurred.
610
#
611
function uninstallVersion {
612
  local versions=("${!1}")
613
  local current_idx="$2"
614
  local linkdir="$3"
615

  
616
  # check whether at least two installations were detected
617
  if [ ${#versions[@]} -eq 0 ]; then
618
    printError "no installation detected\n"
619
    return -1
620
  else
621
    # print all available versions
622
    printInfo "choose the installation to uninstall to or type 'A' to abort:\n"
623
    for (( cnt=0; cnt<${#versions[@]}; ++cnt )); do
624
      if [ $cnt -eq $current_idx ]; then
625
        printf "*%3u: %s\n" $(($cnt + 1)) ${versions[$cnt]}
626
      else
627
        printf " %3u: %s\n" $(($cnt + 1)) ${versions[$cnt]}
628
      fi
629
    done
630

  
631
    # read user selection
632
    printLog "read user slection\n"
633
    local userinput=""
634
    while [ -z $userinput ] ; do
635
      read -p "your selection: " -e userinput
636
      printLog "user selection: $userinput\n"
637
      if [[ ! "$userinput" =~ ^[0-9]+$ ]] || [ ! "$userinput" -gt 0 ] || [ ! "$userinput" -le ${#versions[@]} ] && [[ ! "$userinput" =~ ^[Aa]$ ]]; then
638
        printWarning "Please enter an integer between 1 and ${#versions[@]} or 'A' to abort.\n"
639
        userinput=""
640
      fi
641
      if [ ${#versions[@]} -gt 1 ] && [ $((userinput - 1)) -eq $current_idx ]; then
642
        printWarning "Unable to uninstall currently selected version (as long as there are others).\n"
643
        userinput=""
644
      fi
645
    done
646

  
647
    if [[ "$userinput" =~ ^[Aa]$ ]]; then
648
      printWarning "aborted by user\n"
649
      return 1
650
    else
651
      local idx=$((userinput - 1))
652
      printf "\n"
653
      # prompt selected and aks user for confirmation
654
      printInfo "${versions[$idx]} will be removed. Continue? [y/n]\n"
655
      readUserInput "YyNn" userinput
656
      case "$userinput" in
657
        Y|y)
658
          ;;
659
        N|n)
660
          printWarning "uninstallation process aborted by user\n"
661
          return 1
662
          ;;
663
        *) # sanity check (exit with error)
664
          printError "invalid option: $userinput\n"
665
          return -1
666
          ;;
667
      esac
668
      # find and delete any links pointing to the version to be deleted
669
      for link in `find $linkdir -maxdepth 1 -type l`; do
670
        local l=$link
671
        # follow the link to the actual binary
672
        while [ -L $l ]; do
673
          # differentiate between relative and absolute paths
674
          if [[ $(readlink $l) = /* ]]; then
675
            l=$(readlink $l)
676
          else
677
            l=$(realpath $(dirname $l)/$(readlink $l))
678
          fi
679
        done
680
        # delete the link if it points to the version to be uninstalled
681
        if [ $(dirname $l) == $(dirname ${versions[$idx]}) ]; then
682
          rm $link
683
        fi
684
      done
685
      # delete the version directory (assumed to be one directory up)
686
      rm -rf $(realpath $(dirname ${versions[$idx]})/..)
687
      printInfo "${versions[$idx]} has been removed.\n"
688
    fi
689
  fi
690

  
691
  return 0
692
}
693

  
694
### change default version #####################################################
695
# Change the default arm-none-eabi-gcc version.
696
#
697
# usage:      changeDefaultVersion <versions> <linkdir>
698
# argumenst:  <versions>
699
#                 Array of available versions (full path to binary).
700
#             <linkdir>
701
#                 Path where to delete old and create new links.
702
# return:     0
703
#                 No error or warnign occurred.
704
#             -1
705
#                 Error: no installation detected.
706
#
707
function changeDefaultVersion {
708
  local versions=("${!1}")
709
  local linkdir="$2"
710

  
711
  # check whether an installation was detected
712
  if [ ${#versions[@]} -eq 0 ]; then
713
    printError "no installation detected\n"
714
    return -1
715
  else
716
    # print all available versions
717
    printInfo "choose the installation to switch to or type 'A' to abort:\n"
718
    for (( cnt=0; cnt<${#versions[@]}; ++cnt )); do
719
      printf "  %2u: %s\n" $(($cnt + 1)) ${versions[$cnt]}
720
    done
721

  
722
    # read user selection
723
    printLog "read user slection\n"
724
    local userinput=""
725
    while [[ ! "$userinput" =~ ^[0-9]+$ ]] || [ ! "$userinput" -gt 0 ] || [ ! "$userinput" -le ${#versions[@]} ] && [[ ! "$userinput" =~ ^[Aa]$ ]]; do
726
      read -p "your selection: " -e userinput
727
      printLog "user selection: $userinput\n"
728
      if [[ ! "$userinput" =~ ^[0-9]+$ ]] || [ ! "$userinput" -gt 0 ] || [ ! "$userinput" -le ${#versions[@]} ] && [[ ! "$userinput" =~ ^[Aa]$ ]]; then
729
        printWarning "Please enter an integer between 1 and ${#versions[@]} or 'A' to abort.\n"
730
      fi
731
    done
732

  
733
    if [[ "$userinput" =~ ^[Aa]$ ]]; then
734
      printWarning "aborted by user\n"
735
    else
736
      local idx=$((userinput - 1))
737
      # find and delete old links
738
      rm `find $linkdir -maxdepth 1 -type l | grep -Ev "*[0-9]\.[0-9]\.[0-9]"`
739
      # create new links
740
      local bindir=$(dirname ${versions[$idx]})
741
      ls $bindir | xargs -i ln -sf $bindir/{} $linkdir/{}
742
      printInfo "default version set to $(arm-none-eabi-gcc -dumpversion)\n"
743
    fi
744
  fi
745

  
746
  return 0
747
}
748

  
749
### main function of this script ###############################################
750
# The IDE setup lets the user select an IDE of choice.
751
# As of now, only QtCreator is supported.
752
#
753
# usage:      see function printHelp
754
# arguments:  see function printHelp
755
# return:     0
756
#                 No error or warning occurred.
757
#
758
function main {
759
  # print welcome/info text if not suppressed
760
  if [[ $@ != *"--noinfo"* ]]; then
761
    printWelcomeText
762
  else
763
    printf "######################################################################\n"
764
  fi
765
  printf "\n"
766

  
767
  # if --help or -h was specified, print the help text and exit
768
  if [[ $@ == *"--help"* || $@ == *"-h"* ]]; then
769
    printHelp
770
    printf "\n"
771
    quitScript
772
  fi
773

  
774
  # set log file if specified
775
  if [[ $@ == *"--log"* ]] || [[ $@ == *"--LOG"* ]]; then
776
    # get the parameter (file name)
777
    local cmdidx=1
778
    while [[ ! "${!cmdidx}" = "--log"* ]] && [[ ! "${!cmdidx}" = "--LOG"* ]]; do
779
      cmdidx=$[cmdidx + 1]
780
    done
781
    local cmd="${!cmdidx}"
782
    local logfile=""
783
    if [[ "$cmd" = "--log="* ]] || [[ "$cmd" = "--LOG="* ]]; then
784
      logfile=${cmd#*=}
785
    else
786
      local filenameidx=$((cmdidx + 1))
787
      logfile="${!filenameidx}"
788
    fi
789
    # optionally force silent appending
790
    if [[ "$cmd" = "--LOG"* ]]; then
791
      setLogFile --option=c --quiet "$logfile" LOG_FILE
792
    else
793
      setLogFile "$logfile" LOG_FILE
794
      printf "\n"
795
    fi
796
  fi
797
  # log script name
798
  printLog "this is $(realpath ${BASH_SOURCE[0]})\n"
799

  
800
  # detect installed versions and inform user
801
  local installedversions=()
802
  local currentversion=""
803
  local currentversionidx="n/a"
804
  detectInstalledVersions installedversions currentversion currentversionidx
805
  case "${#installedversions[@]}" in
806
    0)
807
      printInfo "no installation has been detected\n";;
808
    1)
809
      printInfo "1 installation has been detected:\n";;
810
    *)
811
      printInfo "${#installedversions[@]} installations have been detected:\n";;
812
  esac
813
  for (( idx=0; idx<${#installedversions[@]}; ++idx )); do
814
    if [ ${installedversions[$idx]} = "$currentversion" ]; then
815
      printInfo "  * ${installedversions[$idx]}\n"
816
    else
817
      printInfo "    ${installedversions[$idx]}\n"
818
    fi
819
  done
820
  printf "\n"
821

  
822
  # parse arguments
823
  local otherargs=()
824
  while [ $# -gt 0 ]; do
825
    if ( parseIsOption $1 ); then
826
      case "$1" in
827
        -h|--help) # already handled; ignore
828
          shift 1;;
829
        -i|--install)
830
          if [ -z "$currentversion" ]; then
831
            installNewVersion
832
          else
833
            installNewVersion --install=$(realpath $(dirname $currentversion)/../..) --link=$(realpath $(dirname $currentversion)/../..)
834
          fi
835
          detectInstalledVersions installedversions currentversion currentversionidx
836
          printf "\n"; shift 1;;
837
        -u|--uninstall)
838
          if [ ! -z "$currentversion" ]; then
839
            uninstallVersion installedversions[@] $currentversionidx $(realpath $(dirname $currentversion)/../..)
840
            detectInstalledVersions installedversions currentversion currentversionidx
841
          else
842
            printError "no installation detected\n"
843
          fi
844
          printf "\n"; shift 1;;
845
        -c|--change)
846
          if [ ! -z "$currentversion" ]; then
847
            changeDefaultVersion installedversions[@] $(realpath $(dirname $currentversion)/../..)
848
          else
849
            printError "no installation detected\n"
850
          fi
851
          printf "\n"; shift 1;;
852
        -q|--quit)
853
          quitScript; shift 1;;
854
        --log=*|--LOG=*) # already handled; ignore
855
          shift 1;;
856
        --log|--LOG) # already handled; ignore
857
          shift 2;;
858
        --noinfo) # already handled; ignore
859
          shift 1;;
860
        *)
861
          printError "invalid option: $1\n"; shift 1;;
862
      esac
863
    else
864
      otherargs+=("$1")
865
      shift 1
866
    fi
867
  done
868

  
869
  # interactive menu
870
  while ( true ); do
871
    # main menu info prompt and selection
872
    printInfo "GCC setup main menu\n"
873
    printf "Please select one of the following actions:\n"
874
    printf "  [I] - install another version\n"
875
    printf "  [U] - uninstall a version\n"
876
    printf "  [C] - change default version\n"
877
    printf "  [Q] - quit this setup\n"
878
    local userinput=""
879
    readUserInput "IiUuCcQq" userinput
880
    printf "\n"
881

  
882
    # evaluate user selection
883
    case "$userinput" in
884
      I|i)
885
        if [ -z "$currentversion" ]; then
886
          installNewVersion
887
        else
888
          installNewVersion --install=$(realpath $(dirname $currentversion)/../..) --link=$(realpath $(dirname $currentversion)/../..)
889
        fi
890
        detectInstalledVersions installedversions currentversion currentversionidx
891
        printf "\n";;
892
      U|u)
893
        if [ ! -z "$currentversion" ]; then
894
          uninstallVersion installedversions[@] $currentversionidx $(realpath $(dirname $currentversion)/../..)
895
          detectInstalledVersions installedversions currentversion currentversionidx
896
        else
897
          printError "no installation detected\n"
898
        fi
899
        printf "\n";;
900
      C|c)
901
        if [ ! -z "$currentversion" ]; then
902
          changeDefaultVersion installedversions[@] $(realpath $(dirname $currentversion)/../..)
903
        else
904
          printError "no installation detected\n"
905
        fi
906
        printf "\n";;
907
      Q|q)
908
        quitScript;;
909
      *) # sanity check (exit with error)
910
        printError "unexpected argument: $userinput\n";;
911
    esac
912
  done
913

  
914
  exit 0
915
}
916

  
917
################################################################################
918
# SCRIPT ENTRY POINT                                                           #
919
################################################################################
920

  
921
main "$@"
compiler/compilersetup.sh
1
################################################################################
2
# AMiRo-BLT is an bootloader and toolchain designed for the Autonomous Mini    #
3
# Robot (AMiRo) platform.                                                      #
4
# Copyright (C) 2016..2018  Thomas Schöpping et al.                            #
5
#                                                                              #
6
# This program is free software: you can redistribute it and/or modify         #
7
# it under the terms of the GNU General Public License as published by         #
8
# the Free Software Foundation, either version 3 of the License, or            #
9
# (at your option) any later version.                                          #
10
#                                                                              #
11
# This program is distributed in the hope that it will be useful,              #
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of               #
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                #
14
# GNU General Public License for more details.                                 #
15
#                                                                              #
16
# You should have received a copy of the GNU General Public License            #
17
# along with this program.  If not, see <http://www.gnu.org/licenses/>.        #
18
#                                                                              #
19
# This research/work was supported by the Cluster of Excellence Cognitive      #
20
# Interaction Technology 'CITEC' (EXC 277) at Bielefeld University, which is   #
21
# funded by the German Research Foundation (DFG).                              #
22
################################################################################
23

  
24
#!/bin/bash
25

  
26
################################################################################
27
# GENERIC FUNCTIONS                                                            #
28
################################################################################
29

  
30
### print an error message #####################################################
31
# Prints a error <message> to standard output.
32
#If variable 'LOG_FILE' is specified, the message is also appended to the given file.
33
#
34
# usage:      printError <message>
35
# arguments:  <message>
36
#                 Message string to print.
37
# return:     n/a
38
#
39
function printError {
40
  local string="ERROR:   $1"
41
  # if a log file is specified
42
  if [ -n "$LOG_FILE" ]; then
43
    printf "[$(date '+%Y-%m-%d %H:%M:%S')] $string" >> $LOG_FILE
44
  fi
45
  printf "$(tput setaf 1)>>> $string$(tput sgr 0)" 1>&2
46
}
47

  
48
### print a warning message ####################################################
49
# Prints a warning <message> to standard output.
50
#If variable 'LOG_FILE' is specified, the message is also appended to the given file.
51
#
52
# usage:      printMessage <message>
53
# arguments:  <message>
54
#                 Message string to print.
55
# return:     n/a
56
#
57
function printWarning {
58
  local string="WARNING: $1"
59
  # if a log file is specified
60
  if [ -n "$LOG_FILE" ]; then
61
    printf "[$(date '+%Y-%m-%d %H:%M:%S')] $string" >> $LOG_FILE
62
  fi
63
  printf "$(tput setaf 3)>>> $string$(tput sgr 0)"
64
}
65

  
66
### print an information message ###############################################
67
# Prints an information <message> to standard output.
68
#If variable 'LOG_FILE' is specified, the message is also appended to the given file.
69
#
70
# usage:      printInfo <message>
71
# arguments:  <message>
72
#                 Message string to print.
73
# return:     n/a
74
#
75
function printInfo {
76
  local string="INFO:    $1"
77
  # if a log file is specified
78
  if [ -n "$LOG_FILE" ]; then
79
    printf "[$(date '+%Y-%m-%d %H:%M:%S')] $string" >> $LOG_FILE
80
  fi
81
  printf "$(tput setaf 2)>>> $string$(tput sgr 0)"
82
}
83

  
84
### print a message to file ####################################################
85
# Appends a <message> to a log file, specified by the variable 'LOG_FILE'.
86
#
87
# usage       printLog <message>
88
# arguments:  <message>
89
#                 Message string to print.
90
# return:     n/a
91
#
92
function printLog {
93
  local string="LOG:     $1"
94
  # if a log file is specified
95
  if [ -n "$LOG_FILE" ]; then
96
    printf "[$(date '+%Y-%m-%d %H:%M:%S')] $string" >> $LOG_FILE
97
  fi
98
}
99

  
100
### exit the script normally ###################################################
101
# Prints a delimiter and exits the script normally (returns 0).
102
#
103
# usage:      quitScript
104
# arguments:  n/a
105
# return:     0
106
#                 No error or warning occurred.
107
#
108
function quitScript {
109
  printInfo "exiting $(realpath ${BASH_SOURCE[0]})\n"
110
  printf "\n"
111
  printf "######################################################################\n"
112
  exit 0
113
}
114

  
115
### read a user input ##########################################################
116
# Reads a single character user input from a set up <options> and stores it in
117
# a given <return> variable.
118
#
119
# usage:      readUserInput <options> <return>
120
# arguments:  <options>
121
#                 String definiing the set of valid characters.
122
#                 If the string is empty, the user can input any character.
123
#             <return>
124
#                 Variable to store the selected character to.
125
# return:     n/a
126
#
127
function readUserInput {
128
  local input=""
129
  # read user input
130
  while [ -z $input ] || ( [ -n "$1" ] && [[ ! $input =~ ^[$1]$ ]] ); do
131
    read -p "your selection: " -n 1 -e input
132
    if [ -z $input ] || ( [ -n "$1" ] && [[ ! $input =~ ^[$1]$ ]] ); then
133
      printWarning "[$input] is no valid action\n"
134
    fi
135
  done
136
  printLog "[$input] has been selected\n"
137
  eval $2="$input"
138
}
139

  
140
### check whether argument is an option ########################################
141
# Checks a <string> whether it is an option.
142
# Options are defined to either start with '--' followed by any string, or
143
# to start with a single '-' followed by a single character, or
144
# to start with a single '-' followed by a single character, a '=' and any string.
145
# Examples: '--option', '--option=arg', '-o', '-o=arg', '--'
146
#
147
# usage:      parseIsOption <string>
148
# arguments:  <string>
149
#                 A string to check whether it is an option.
150
# return:     0
151
#                 <string> is an option.
152
#             -1
153
#                 <string> is not an option.
154
#
155
function parseIsOption {
156
  if [[ "$1" =~ ^-(.$|.=.*) ]] || [[ "$1" =~ ^--.* ]]; then
157
    return 0
158
  else
159
    return -1
160
  fi
161
}
162

  
163
### set the log file ###########################################################
164
# Sets a specified <infile> as log file and checks whether it already exists.
165
# If so, the log may either be appended to the file, its content can be cleared,
166
# or no log is generated at all.
167
# The resulting path is stored in <outvar>.
168
#
169
# usage:      setLogFile [--option=<option>] [--quiet] <infile> <outvar>
170
# arguments:  --option=<option>
171
#                 Select what to do if <file> already exists.
172
#                 Possible values are 'a', 'c', 'r' and 'n'.
173
#                 - a: append (starts with a separator)
174
#                 - c: continue (does not insert a seperator)
175
#                 - r: delete and restart
176
#                 - n: no log
177
#                 If no option is secified but <file> exists, an interactive selection is provided.
178
#             --quiet
179
#                 Suppress all messages.
180
#             <infile>
181
#                 Path of the wanted log file.
182
#             <outvar>
183
#                 Variable to store the path of the log file to.
184
# return:     0
185
#                 No error or warning occurred.
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff