Wiki

This version is outdated by a newer approved version.DiffThis version (04 Nov 2011 09:41) is a draft.
Approvals: 0/1

This is an old revision of the document!


Firmware Loader for SigmaDSPs

Parts that include the SigmaDSP processor can be loaded with arbitrary code that is generated by SigmaStudio. A firmware driver has been written to help simplify the process of parsing and loading this binary firmwares.

This code and related firmware specification is currently under development

Helper Functions

You should only need to invoke one function in order to load a binary blob:

extern int process_sigma_firmware(struct i2c_client *client, const char *name);

You pass the I2C client of the connected SigmaDSP and the name of the firmware blob to load (which normally corresponds to the modetype attribute of the page element).

Firmware Blob Format

The XML format allows multiple page elements (with each including their own set of action elements), but the firmware blob format splits each page element into its own binary file. Otherwise, a lot of needless seeking/indexing would be required in the firmware format itself in order to support this. Filesystems are already pretty good at this kind of thing, and most people will only need a small number of firmware blobs in the first place.

Every firmware blob has a header which includes a magic string, version format identifier, and crc: <source trunk/include/linux/sigma.h:sigma_firmware_header{} c linux-kernel>

Then there are an arbitrary number of actions (which correspond to the action xml element). <source trunk/include/linux/sigma.h:sigma_action{} c linux-kernel>

The instr field can be a few different things. Currently pllwait/noop are ignored, and the end action is redundant (end of file means end of page data). <source trunk/include/linux/sigma.h:/SIGMA_ACTION_/-/}/ c linux-kernel>

The len and len_hi fields can be combined to get the length of the payload for the action. Whether this value needs to be subtracted by 2 is not yet decided (the original action xml element declares the length as number of payload bytes + number of bytes for i2c register address). <source trunk/include/linux/sigma.h:sigma_action_len() c linux-kernel>

The addr field is the 16bit I2C register to write the payload to in the device.

Each action must be padded to 16bits so that the structure can easily be read directly from the file without having to worry about unaligned issues. That means if the payload is not a multiple of 16bits, then it will have a pad byte appended to it automatically. There is a helper function for this: <source trunk/include/linux/sigma.h:sigma_action_size() c linux-kernel>

XML -> Firmware Blob

While the typical output of SigmaStudio is an XML file, processing this on the board would force a lot of ugly overhead. Until it supports exporting directly to a firmware blob, this shell script can be used to convert things.

#!/bin/bash
set -e

err() { echo "$*" 1>&2; }

unset end

export \
	INSTR_writexbytes=0 \
	INSTR_writesingle=1 \
	INSTR_writesafeload=2 \
	INSTR_delay=3 \
	INSTR_pllwait=4 \
	INSTR_noop=5 \
	INSTR_end=6

awk 'BEGIN {
	printf "ADISIGM%c", 1;
	printf "%c%c%c%c", 0, 0, 0, 0;
}'

xml sel -t -c ROM/page/action "$1" | \
	perl -p -e 's:\n::g' | \
	sed \
		-e 's:/>:\n:g' \
		-e 's:</action>:\n:g' \
		-e 's:<action ::g' \
		-e 's:ParamName="[^"]*"::g' \
		-e 's:CellName="[^"]*"::g' | \
	sed -e 's: *>\(.*\): data="\1":' | \
	tr '[:upper:]' '[:lower:]' | \
while read line ; do
	if [ "${end}" = "true" ] ; then
		err "error: too much input; page is supposed to be over"
		exit 1
	fi

	unset instr len addr data
	eval $line
	export instr len addr data
	data=$(set -- ${data}; echo ${@/#/0x})
	rlen=${len:-0}

	case $instr in
		writexbytes);;
		writesingle) len=3;;
		writesafeload);;
		delay) len=$(printf '%i' $data); unset data; rlen=0;;
		pllwait|noop) err "ignoring unsupported instruction: $instr"; continue;;
		end) end=true; continue;;
	esac

	instr="INSTR_${instr}"
	err "LINE: $line {inst:${!instr} rlen:${rlen}}"

#struct sigma_action {
#   uint8_t instr;
#   uint8_t len_hi;
#   uint16_t len;
#   uint16_t addr;
#   unsigned char payload[];
#};

#	awk 'BEGIN{printf "%i", '${!instr}';}'
	php -B "
		printf('%c', ${!instr});         /* instr */
		printf('%c', 0);                 /* len_hi */
		printf('%c', $((len % 256)));    /* len (msb) */
		printf('%c', $((len / 256)));    /* len (lsb) */
		printf('%c', $((addr % 256)));   /* addr (msb) */
		printf('%c', $((addr / 256)));   /* addr (lsb) */
		\$a = explode(' ', '${data}');
		if (!(count(\$a) == 1 && \$a[0] == '')) {
			foreach (\$a as \$d) { printf('%c', 0+\$d); }
			if (count(\$a) % 2 == 1) printf('%c', 0);
		}
	" </dev/null || exit
done
resources/tools-software/linux-drivers/sound/sigma.1320396113.txt.gz · Last modified: 04 Nov 2011 09:41 by Lars-Peter Clausen