Revision d796dcdf README.txt

View differences:

README.txt
69 69
    4.1  Adding a New Module
70 70
    4.2  Handling a Custom I/O Event in the Main Thread
71 71
    4.3  Implementing a New Low-Level Driver
72
    4.4  Writing a Unit Test
72
    4.4  Writing a Test
73 73

  
74 74
================================================================================
75 75

  
......
101 101
directory. Note that you will have to adapt the makefiles and scripts, and
102 102
probably the operating system as well.
103 103
AMiRo-BLT furthermore has its own required and recommended software tools as
104
described in its README.txt file. Follow th instructions to initialize the
104
described in its README.txt file. Follow the instructions to initialize the
105 105
development environment manually or use the ./setup.sh script.
106 106

  
107 107

  
......
112 112
copy of it as well. For the sake of compatibility, it is included in AMiRo-OS as
113 113
a Git submodule. It is highly recommended to use the ./setup.sh script for
114 114
initialization. Moreover, you have to apply the patches to ChibiOS in order to
115
make AMiRo-OS work properly. It is recommended to use the .setup.sh script for
115
make AMiRo-OS work properly. It is recommended to use the ./setup.sh script for
116 116
this purpose.
117 117
If you would like to use a different kernel, you can add a subfolder in the
118 118
./kernel/ directory and adapt the scripts and operating system source code.
......
164 164
AMiRo-BLT, you can replace the port value by '/dev/ttyUSB0'.
165 165
Advanced users can use several connections to multiple modules simultaneously.
166 166
Each additional programmer will be available as '/dev/ttyAMiRo<N>' (and
167
'/dev/USB<N>' respectively) with <N> being an integer number starting from zero.
168
Please note: Those interfaces are ordered by the time when they have been
169
detected by the operating system.
167
'/dev/ttyUSB<N>' respectively) with <N> being an integer number starting from
168
zero. Please note: Those interfaces are ordered by the time when they have been
169
detected by the operating system, so detaching a cable and plugging it in again
170
may result in a different port name.
170 171

  
171 172

  
172 173
2.2 - QtCreator IDE
173 174
-------------------
174 175

  
175
In order to setup QtCreator projects for the three AMiRo base modules, you can
176
use the provided ./setup.sh script. Further instructions for a more advanced
176
In order to setup QtCreator projects any supported module, you can use the
177
provided ./setup.sh script. Further instructions for a more advanced
177 178
configuration of the IDE are provided in the ./tools/qtcreator/README.txt file.
178 179

  
179 180

  
......
193 194
Each time you modify any part of AMiRo-OS, you need to recompile the whole
194 195
project for the according AMiRo module. Therefore you can use the ./Makefile by
195 196
simply executing 'make' and follow the instructions. Alternatively, you can
196
either use the makefiles provided per module in ./os/modules/<ModuleToCompile>
197
either use the makefiles provided per module in ./os/modules/<module_to_compile>
197 198
or - if you want to compile all modules at once - the makefile in the
198 199
./os/modules folder. After the build process has finished successfully, you
199
always have to flash the generated program to the robot. Therefore you need an
200
always have to flash the generated program to the module. Therefore you need an
200 201
appropriate tool, such as stm32flash (if you don't use a bootloader) or
201 202
SerialBoot (highly recommended; provided by AMiRo-BLT). Similarly to the
202 203
compilation procedure as described above, you can flash either each module
......
229 230
should be as unambiguous as possible (e.g. containing name and version number).
230 231
All files, which directly depent on the hardware, and thus are not portable,
231 232
belong here. Conversely, any code that can be reused on diferent hardware must
232
not be put in the module folder.
233
not be put in this module folder.
233 234

  
234 235
In a second step you have to initialize all requried files (see below) in the
235
newlly created module directory. It is recommended to use another module as
236
newly created module directory. It is recommended to use another module as
236 237
template for your configuration:
237 238
- alldconf.h
238 239
  Configuration header for the AMiRo-LLD project, which is part of AMiRo-OS.
240
  There are probably only very few configurations done here, since most setting
241
  depend on the content of aosconf.h and are handled modue unspecifically in in
242
  modules/aos_alldconf.h
239 243
- aosconf.h
240 244
  Configuration header for the AMiRo-OS project.
241 245
- board.h & board.c
......
243 247
  well as initialization functions.
244 248
- chconf.h
245 249
  Configuration header for the ChibiOS/RT system kernel. There are probably only
246
  very few configurations one here, since most settings depend on the content of
247
  aosconf.h and are handled module unspecific in modules/aos_chconf.h
250
  very few configurations done here, since most settings depend on the content
251
  of aosconf.h and are handled module unspecifically in modules/aos_chconf.h
248 252
- halconf.h
249 253
  Configuration header for ChibiOS/HAL (hardware abstraction layer).
250 254
- Makefile
251 255
  The GNU make script to build and flash AMiRo-OS for the module.
252 256
- mcuconf.h
253
  Configuration file for ChibiOS/JAL to initialize the microcontroller (MCU). It
257
  Configuration file for ChibiOS/HAL to initialize the microcontroller (MCU). It
254 258
  is recommended to check the kernel/ChibiOS/demos/ directory for an example
255 259
  using the according MCU and copy the mcuconf.h from there. Depending on your
256 260
  hardware you may have to modify it nevertheless, though.
......
271 275
settings are used in other modules.
272 276

  
273 277
Finally, you need to build and flash the project. The compiler might even help
274
you getting everything set up correctly. Take time to understand compilation
275
errors and warning and get rid of all of those (warnings should not be ignored
276
since they are hints that something might be amiss and the program will not act
277
as intended).
278
you getting everything set up correctly. Take the time needed to understand
279
compilation errors and warnings and get rid of all of those (warnings should not
280
be ignored since they are hints that something might be amiss and the program
281
will not act as intended).
278 282

  
279 283
Summing up, you have to
280 284
1) create a module directory.
......
288 292

  
289 293
In order to handle custom I/O events in the main thread, AMiRo-OS offers several
290 294
hooks to be used. First of all, you need to configure and enable the interrupt
291
in the according GPIO. This can be done by implementing the
295
for the according GPIO. This can be done by implementing the
292 296
MODULE_INIT_INTERRUPTS() hook in the module.h file. For information how to use
293 297
this hook, please have a look at existing modules. In the end, the interrupt
294 298
callback functions has to emit an I/O event with the according bit in the flags
295
mask set (like the _intCallback() function in aos_system.c). As result, whenever
296
a rising or falling edge (depends on configuration) is detected on that GPIO,
297
the interrupt service routine is executed and hence an I/O event is fired, which
298
can be catched by any thread in the system.
299
mask set (like the _gpioCallback() function in aos_system.c). As result,
300
whenever a rising or falling edge (depends on configuration) is detected on that
301
particular GPIO, the interrupt service routine is executed and hence an I/O
302
event is fired, which can be catched by any thread in the system.
299 303

  
300 304
Next, you have to configure the main thread to whitelist the event flag (all I/O
301 305
events are blacklisted by default). While system relevant events like power down
302
are whitelisted by the OS, any custom events need to be added exl´plicitely.
303
This is done via the optional AMIROOS_CFG_MAIN_LOOP_GPIOEVENT_FLAGSMASK macro,
304
which should be defined in the module.h file. Example:
306
are imlicitely whitelisted by the OS, any custom events need to be added
307
exlplicitely. This is done via the optional
308
AMIROOS_CFG_MAIN_LOOP_GPIOEVENT_FLAGSMASK macro, which should be defined in the
309
module.h file. Example:
305 310

  
306 311
  #define AMIROOS_CFG_MAIN_LOOP_GPIOEVENT_FLAGSMASK         \
307 312
    (AOS_GPIOEVENT_FLAG(padX) | AOS_GPIOEVENT_FLAG(padY) | AOS_GPIOEVENT_FLAG(padZ))
......
309 314
When AMIROOS_CFG_MAIN_LOOP_GPIOEVENT_FLAGSMASK has been defined correctly, the
310 315
main thread will be notified by the according events and execute its event
311 316
handling routine. Hence you have to implement another macro in module.h to
312
handle the custom event(s) appropriately: MODULE_MAIN_LOOP_GPIOEVENT(eventflags).
313
As you can see, the variable 'eventflags' is propagated to the hook. This
314
variable is a mask, that allows to identify the GPIO pad(s), which caused the
315
event, by the bits set. Following the example above, you can check which GPIOs
316
have caused events by using if-clauses in the implementation of the hook:
317
handle the custom event(s) appropriately:
318
MODULE_MAIN_LOOP_GPIOEVENT(eventflags). As you can see, the variable
319
'eventflags' is propagated to the hook. This variable is a mask, that allows to
320
identify the GPIO pad(s), which caused the event, by the individually set bits.
321
Following the example above, you can check which GPIOs have caused events by
322
using if-clauses in the implementation of the hook:
317 323

  
318 324
  #define MODULE_MAIN_LOOP_GPIOEVENT(eventflags) {          \
319 325
    if (eventflags & AOS_GPIOEVENT_FLAG(padX)) {            \
......
337 343
In the AMiRo-OS framework, low-level drivers are located in the additional Git
338 344
project AMiRo-LLD, which is included in AMiRo-OS as Git submodule at
339 345
periphery-lld/AMiRo-LLD/ and acts similar to a static library. When adding a new
340
low-level driver to the framework, you have to implement it, providing a
341
(single) header file in periphery-lld/AMiRo-LLD/include/ and the required C
342
sources in periphery-lld/AMiRo-LLD/source/. By convention, all filenames use the
343
prefix 'alld_' to avoid ambiguities. Furthermore, files should be named by the
344
exact designation of the hardware (e.g. 'alld_vcnl4020' instead of
345
'alld_proximitysensor'). Since AMiRo-LLD is intended to be usable with other
346
operating systems than AMiRo-OS, it provides an interface for accessing
347
communication interfaces and basic functionalities of the operating system. On
348
the one hand, several types are defined in periphery-lld/AMiRo-LLD/periphALtypes.h.
349
The interface functions, on the other hand, are defined by AMiRo-LLD (cf.
350
periphery-lld/AMiRo-LLD/templates/periphAL.h), but implemented by the operating
351
system (cf. periphery-lld/periphAL.h). For the implementation of the driver, you
352
must only use those types and functions to interact with the operating system.
353
If you need further functionality, which is not provided by the interface yet,
354
you are encouraged to extend periphAL.
355

  
356
Furthermore, all files must define a guard, so that the whole driver is
357
disabled, when the guard is not set explicitely. These guard again are named
358
following a convention, but instead of explaning it here, just have a look at
359
one of the existing drivers and look for lines like
360

  
361
  #if defined(AMIROLLD_CFG_USE_VCNL4020) || defined(__DOXYGEN__)
362

  
363
With these guards in place, the driver will be omitted by default and needs to
364
be enabled explicitely. In order to do so, you need to add an according #define
365
in the alldconf.h file of any module, which shall use the new driver.
366

  
367
Now the new driver is available and enabled, but not actually used yet.
368
Therefore you have to add according memory structures to the module.h and
346
low-level driver to the framework, you have to implement it, following the
347
instructions given in periphery-lld/AMiRo-LLD/README.txt
348

  
349
Now the new driver is available and can be enbled by simply including the
350
driver's makefile script in the module makefile. In order to make actuale use of
351
the driver you have to add according memory structures to the module.h and
369 352
module.c files - just have a look at existing modules how this is done. In some
370 353
cases you will have to configure additional interrupts and/or alter the
371 354
configuration of a communication interface (e.g. I²C). Once again, you should
372 355
take a look at existing modules and search the module.h for the hooks
373
MODULE_INIT_INTERRUPTS() and MODULE_INIT_PERIPHERY_COMM().
356
MODULE_INIT_INTERRUPTS(), MODULE_INIT_PERIPHERY_IF and
357
MODULE_SHUTDOWN_PERIPHERY_IF().
374 358

  
375
Finally, you will probably want to validate your implementation via a unit test.
376
How this can be done is explained in detail in the next guide.
359
Finally, you will probably want to validate your implementation via a test. How
360
this can be done is explained in detail in the next guide.
377 361

  
378 362
Summing up, you have to
379 363
1) implement the driver in AMiRo-LLD using periphAL only.
380
2) fence all code in all files by a guard.
381
3) set the guard in alldconf.h to enable the driver.
382
4) add the driver to a module.
364
4) add the driver to a module (Makefile, module.h and module.c).
383 365
5) configure interrupts and interfaces as required.
384
6) write a unit test.
366
6) write a test.
385 367

  
386 368

  
387
4.4  Writing a Unit Test
369
4.4  Writing a Test
388 370
------------------------
389 371

  
390
AMiRo-OS provides a unit test framework for conventient testing and the ability
391
to opt-out all unit tests via the aosconf.h configuration file. There is also a
392
dedicated folder, where all unit test code belongs to. In case you want to
393
implement a unit test for a newly developed low-level driver, you should use the
394
folders unittests/periphery-lld/inc and unittests/periphery-lld/src
395
respectively. As with the low-level drivers, unit test files should use a prefix
396
in their name, namely 'ut_' and all code should be fenced via guards that
397
disable it by default (have a look at existing unit tests). Before you implement
398
a vast test, however, it is highly recommended to start with some sceleton code
399
(just copy an existing unit test, scoop out the test function, and rename
400
according variables etc.) and make it compile and run.
401

  
402
After you have initialized the unit test sceleton, you have to add the according
403
aos_unittest_t (cf. core/inc/aos_unittest.h) object to the module.h and module.c
404
files. These objects again require an shell command, so the unit test can be run
405
via the AMiRo-OS shell. As with existing unit tests, this shell command callback
406
function as well as any further required data should be implemented directly in
407
module.c, so it not accessable from any other context. In most cases this
408
callback function is trivial, anyway.
409

  
410
In order to make the shell command, which executes the unit test, available in
411
shell so a user can run it, it has to be associated with the shell. AMiRo-OS
412
provides the hook MODULE_INIT_TESTS() for this purpose, which has to be
413
implemented in the module.h file. Once again I recommend to have a look at an
414
existing module, how to use this hook.
415

  
416
Since the execution pipeline is set up now, you can fille your unit test with
417
life. Remember that the test is executed by the shell thread, so you can access
418
any functionality of the system, but might encounter race conditions, depending
419
on what other applications run concurrently.
372
AMiRo-OS provides a test framework for conventient testing and the ability to
373
opt-out all tests via the aosconf.h configuration file. There is also a
374
dedicated folder, where all test code belongs to. In case you want to implement
375
a test for a newly developed low-level driver, you should have a look at the
376
folder test/periphery-lld/. As with the low-level drivers, tests are placed in
377
individual subfolders (e.g. test/periphery-lld/DEVICE1234_v1) and all should use
378
the prefix 'aos_test_' in their name. Moreover, all code must be fenced by
379
guards that disable it completely if the AMIROOS_CFG_TESTS_ENABLE flag is set to
380
false in the aosconf.h configuration file.
381

  
382
Now you will need to add the test to a specific module. Therefore, you should
383
create a new test/ directory in the module folder, if such does not exist yet.
384
In this directory, you create another subfolder, e.g. DEVICE1234/ and three
385
additional files in there:
386
 - module_test_DEVICE1234.mk
387
 - module_test_DEVICE1234.h
388
 - module_test_DEVICE1234.c
389
The makefile script is not required, but recommended to achieve maintainable
390
code. This script file should add the folder to the MODULE_INC variable and all
391
C source files to MODULE_CSRC. The .h and .c files furthermore define module
392
specific data structures and a test function.
393

  
394
In order to be able to call this function as a command via the AMiRo-OS shell,
395
you need to add an according shell command to the module.h and module.c files.
396
Whereas the command itself is typically very simple, just calling the callback
397
function defined in the test/DEVICE1234/module_test_DEVICE1234.h/.c files, you
398
have to add the command to a shell. In order to make the shell command, which
399
executes the test, available in a shell so a user can run it, it has to be
400
associated with the shell. AMiRo-OS provides the hook MODULE_INIT_TESTS() for
401
this purpose, which has to be implemented in the module.h file. Once again I
402
recommend to have a look at an existing module, how to use this hook.
420 403

  
421 404
Summing up, you have to
422
1) initialize a unit test sceleton in the unittests/ folder.
423
2) introduce an according object and configuration in module.h and module.c.
405
1) implement the test in the test/ folder.
406
2) implement a module specific wrapper in the module/test/ folder.
424 407
3) associate the shell command to a shell via the hook in module.h.
425
4) implement the full unit test in the prevously created sceleton files.
426 408

  
427 409
================================================================================
428 410

  

Also available in: Unified diff