понедельник, 17 декабря 2012 г.

Tags generation for ASF project

If you use Atmel Software Framework you can generate tags (with ctags|GNU Global) for your Vim/Emacs environment in such way (in Makefile):
ctags = c:/Program Files/ctags.exe
gtags = c:/global/bin/gtags.exe
sed = c:/MinGW/msys/1.0/bin/sed.exe
find = c:/MinGW/msys/1.0/bin/find.exe

GTAGS_FILES = GTAGS GPATH GRTAGS
# Global can not parse out of c:/prj/PRJ1/src
TAGS_DIRS = 'c:/Program Files/Atmel/Atmel Studio 6.0/extensions/Atmel/AVRGCC/3.3.2.31/AVRToolchain/avr32/include' \
   c:/prj/PRJ1/src/asf-3.0.1 \
   c:/prj/PRJ1/src/PRJ1

tags.files: force
 $(find) $(TAGS_DIRS) -type f -name *.S -or -name *.h -or -name *.c|$(sed) 's/c:\/prj\/PRJ1\/src/./g' >tags.files

$(GTAGS_FILES): tags.files
 $(gtags) -f tags.files

.PHONY: global_tags
global_tags: $(GTAGS_FILES)

tags: tags.files
 $(ctags) -L tags.files

.PHONY: all_tags
all_tags: tags global_tags

.PHONY: clean_tags
clean_tags:
 rm -f $(GTAGS_FILES) tags
I suppose in this example you use Windows, have MinGW (with find, sed utils). Project is located in c:\prj and has name PRJ1. To generate use targets: tags, global_tags or all_tags. tags file will be about 100 MB, Global tags files will be about 70 MB, but Global can not parse files out of source tree, so avr32/include will be missed - use ctags instead of.

Calculating timer/clock parameters (prescalers) for 'tick' generation with AVR32

Task similar to this (AVR) but for AVR32 with usage of ASF. If we need to generate ticks, we can use one of wave generation mode of AVR32 TCs. For this we need to define value of RC register and to select clock source (internal line). We use PBA line divided by 2, 8, 32, 128 dividers (so sources are TC_CLOCK_SOURCE2..5 in ASF 'terminology' - macroses :).
Here is the source of calculator of RC, divider:
#include <stdint.h>
#include <limits.h>

// max value of RC register with type uint16_t (unsigned short of AVR32 GCC)
#define MAX_RC (1<<(sizeof(uint16_t)*CHAR_BIT))
int
calc_tc_params(long *freq, long *err, uint16_t *presc, uint16_t *rc)
{
        static const long divs[] = {2, 8, 32, 128};
        static const int ndivs = sizeof divs/sizeof divs[0];
        long _err = 0, _merr = *err;
        uint16_t _rc = 0, _mrc = 0, _idiv = 0, _midiv = 0;

        for (_idiv = 0; _idiv < ndivs; _idiv++) {
                _rc = (FPBA / divs[_idiv]) / (*freq);
                _rc = (_rc==0? 1 : _rc>MAX_RC? MAX_RC : _rc);
                _err = abs((*freq) - (FPBA / divs[_idiv]) / (long)_rc);
                if (_err <= _merr) {
                        _merr = _err;
                        _midiv = _idiv;
                        _mrc = _rc;
                }
                if (!_err) break;
        }

        if (_mrc) {
                *rc = _mrc;
                *err = _merr;
                *presc = divs[_midiv];
                *freq = (FPBA / divs[_midiv]) / _mrc;
                return (1);
        } else
                return (0);
}
NOTE: FPBA is the frequency of PBA line. Inputs are:
  • freq - frequency in Hz
  • err - absolute error in Hz
Outputs are:
  • freq - real frequency for calculated params
  • err - real absolute error
  • presc - divider value (2..128)
  • rc - value for RC register to load
Timer source can be found in this way:
#define PRESC2TCSRC(PRESC) ((PRESC)==2? TC_CLOCK_SOURCE_TC2 \
                            :(PRESC)==8? TC_CLOCK_SOURCE_TC3 \
                            :(PRESC)==32? TC_CLOCK_SOURCE_TC4 \
                            :(PRESC)==128? TC_CLOCK_SOURCE_TC5 \
                            :-1)
and it's result should be used as tcclks member of tc_waveform_opt_t struct.
On success, returns 1, 0 otherwise.
For more information how to start 'ticks' generation, see ASF example TC_EXAMPLE3 of TC module.