How to guides

Assembly Programming Manual

The XMOS assembly language supports the formation of objects in the
Executable and Linkable Format
(ELF)

with DWARF 3
debugging information.
Extensions to the ELF format are documented in the XMOS Application
Binary Interface

.

Lexical Conventions

There are six classes of tokens: symbol names, directives, constants,
operators, instruction mnemonics and other separators. Blanks, tabs,
formfeeds and comments are ignored except as they separate tokens.

Comments

The character # introduces a comment, which terminates with a
newline. Comments do not occur within string literals.

Symbol Names

A symbol name begins with a letter or with one of the characters
.‘, ‘_‘ or ‘$‘, followed by an optional sequence of letters,
digits, periods, underscores and dollar signs. Upper and lower case
letters are different.

Directives

A directive begins with ‘.‘ followed by one or more letters.
Directives instruct the assembler to perform some action (see Directives
).

Constants

A constant is either an integer number, a character constant or a string
literal.

  • A binary integer is 0b or 0B followed by zero or more of the
    digits 01.
  • An octal integer is 0 followed by zero or more of the digits
    01234567.
  • A decimal integer is a non-zero digit followed by zero or more of the
    digits 0123456789.
  • A hexadecimal integer is 0x or 0X followed by one or more of
    the digits and letters 0123456789abcdefABCDEF.
  • A character constant is a sequence of characters surrounded by single
    quotes.
  • A string literal is a sequence of characters surrounded by double
    quotes.

The C escape sequences may be used to specify certain characters.

Sections and Relocations

Named ELF sections are specified using directives (see section, pushsection, popsection
).
In addition, there is a unique
unnamed “absolute” section and a unique unnamed “undefined” section. The
notation {secname X} refers to an “offset X into section secname.”

The values of symbols in the absolute section are unaffected by
relocations. For example, address {absolute 0} is “relocated” to
run-time address 0. The values of symbols in the undefined section are
not set.

The assembler keeps track of the current section. Initially the current
section is set to the text section. Directives can be used to change the
current section. Assembly instructions and directives which allocate
storage are emitted in the current section. For each section, the
assembler maintains a location counter which holds the current offset in
the section. The active location counter refers to the location
counter for the current section.

Symbols

Each symbol has exactly one name; each name in an assembly program
refers to exactly one symbol. A local symbol is any symbol beginning
with the characters “.L”. A local symbol may be discarded by the
linker when no longer required for linking.

Attributes

Each symbol has a value, an associated section and a binding. A
symbol is assigned a value using the set or linkset directives
(see set, linkset
), or through its use in a label (see Labels
).
The default binding of symbols in the undefined
section is global; for all other symbols the default binding is
local.

Labels

A label is a symbol name immediately followed by a colon (:). The
symbol’s value is set to the current value of the active location
counter. The symbol’s section is set to the current section. A symbol
name must not appear in more than one label.

Expressions

An expression specifies an address or value. The result of an expression
must be an absolute number or an offset into a particular section. An
expression is a constant expression if all of its symbols are defined
and it evaluates to a constant. An expression is a simple expression if
it is one of a constant expression, a symbol, or a symbol ± a constant.
An expression may be encoded in the ELF-extended expression section and
its value evaluated by the linker (see set, linkset
);
the encoding scheme is determined by the ABI. The syntax of an
expression is:

expression ::= unary-exp
| expression infix-op unary-exp
| unary-exp ? unary-exp $: unary-exp
| function-exp
unary-exp ::= argument
| prefix-op unary-exp
argument ::= symbol
| constant
| ( expression )
function-exp ::= $overlay_region_ptr ( symbol )
| $overlay_index ( symbol )
| $overlay_physical_addr ( symbol )
| $overlay_virtual_addr ( symbol )
| $overlay_num_bytes ( symbol )
infix-op ::= one of
+ - < > <= >= || << >> * $M $A & /
prefix-op ::= one of
- ~ $D

Symbols are evaluated to {section x} where section is one of a
named section, the absolute section or the undefined section, and x is
a signed 2’s complement 32-bit integer.

Infix operators have the same precedence and behavior as C, and
operators with equal precedence are performed left to right. In
addition, the $M operator has lowest precedence, and the $A
operator has the highest precedence.

For the + and - operators, the set of valid operations and
results is given in the table below.
For the $D operator, the argument must be a symbol; the result is
1 if the symbol is defined and 0 otherwise.

Valid operations for + and - operators

Op

Left Operand

Right Operand

Result

+

{section x}

{absolute y}

{section x+y}

+

{absolute x}

{section y}

{section x+y}

+

{absolute x}

{absolute y}

{absolute x+y}

-

{section x}

{section y}

{absolute x-y}

-

{section x}

{absolute y}

{section x-y}

-

{absolute x}

{absolute y}

{absolute x-y}

The ? operator is used to select between symbols: if the first
operand is non-zero then the result is the second operand, otherwise the
result is the third operand.

The operators $overlay_region_ptr, $overlay_index,
$overlay_physical_addr, $overlay_virtual_addr and $overlay_num_bytes
can be used to query properties of the overlay containing the overlay roots
with the specified overlay key symbol (see Overlay Directives
).
The set of results of these operators is given in
the table below.

Operators for querying properties of overlays.

Operator

Result

$overlay_region_ptr

Virtual address of the overlay region containing the overlay.

$overlay_index

Index of the overlay in the overlay region.

$overlay_physical_addr

Physical address of the overlay.

$overlay_virtual_addr

Virtual (runtime) address of the overlay.

$overlay_num_bytes

Size of the overlay in bytes.

For all other operators, both arguments must be absolute and the result
is absolute. The $M operator returns the maximum of the two operands
and the $A operator returns the value of the first operand aligned
to the second.

Wherever an absolute expression is required, if omitted then {absolute
0} is assumed.

Directives

Directives instruct the assembler to perform some action. The supported
directives are given in this section.

add_to_set

The add_to_set directive adds an expression to a set of expressions
associated with a key symbol. Its syntax is:

add-to-set-directive ::= .add_to_set symbol , expression
| .add_to_set symbol , expression , symbol

An optional predicate symbol may be specified as the 3rd argument. If this
argument is specified the expression will only be added to the set if the
predicate symbol is not eliminated from the linked object.

max_reduce, sum_reduce

The max_reduce directive computes the maximum of the values of the
expressions in a set. The sum_reduce directive computes the sum of the
values of the expressions in a set.

max-reduce-directive ::= .max_reduce symbol , symbol , expression

sum-reduce-directive ::= .sum_reduce symbol , symbol , expression

The first symbol is defined using the value computed by the directive.
The second symbol is the key symbol identifying the set of expressions (see
add_to_set
). The expression specifies the initial
value for the reduction operation.

align

The align directive pads the active location counter section to the
specified storage boundary. Its syntax is:

align-directive ::= .align expression

The expression must be a constant expression; its value must be a power
of 2. This value specifies the alignment required in bytes.

ascii, asciiz

The ascii directive assembles each string into consecutive
addresses. The asciiz directive is the same, except that each string
is followed by a null byte.

ascii-directive ::= .ascii string-list
| .asciiz string-list
string-list ::= string-list , string
| .asciiz string

byte, short, int, long, word

These directives emit, for each expression, a number that at run-time is
the value of that expression. The byte order is determined by the
endianness of the target architecture. The size of numbers emitted with
the word directive is determined by the size of the natural word on the
target architecture. The size of the numbers emitted using the other
directives are determined by the sizes of corresponding types in the
ABI.

value-directive ::= value-size exp-list
value-size ::= .byte
| .short
| .int
| .long
| .word
exp-list ::= exp-list , expression
| expression

file

The file directive has two forms.

file-directive ::= .file string
| .file constant string

When used with one argument, the file directive creates an ELF
symbol table entry with type STT_FILE and the specified string
value. This entry is guaranteed to be the first entry in the symbol
table.

When used with two arguments the file directive adds an entry to the
DWARF 3 .debug_line file names table. The first argument is a unique
positive integer to use as the index of the entry in the table. The
second argument is the name of the file.

loc

The .loc directive adds a row to the DWARF 3
.debug_line line number matrix.

loc-directive ::= constant constant constantopt
| constant constant constant ⟨loc-option⟩*
loc-option ::= basic_block
| prologue_end
| epilogue_begin
| is_stmt constant
| isa constant

The address register is set to active location counter. The first two
arguments set the file and line registers respectively. The optional
third argument sets the column register. Additional arguments set
further registers in the .debug_line state machine.

basic_block

Sets basic_block to true.

prologue_end

Sets prologue_end to true.

epilogue_begin

Sets epilogue_begin to true.

is_stmt

Sets is_stmt to the specified value, which must be 0 or 1.

isa

Sets isa to the specified value.

weak

The weak directive sets the weak attribute on the specified symbol.

weak-directive ::= .weak symbol

globl, global, extern, locl, local

The globl directive makes the specified symbols visible to other
objects during linking. The extern directive specifies that the
symbol is defined in another object. The locl directive specifies a
symbol has local binding.

visibility ::= .globl
| .extern
| .locl
| .global
| .extern
| .local
vis-directive ::= visibility symbol
| visibility symbol , string

If the optional string is provided, an SHT_TYPEINFO entry is created
in the ELF-extended type section which contains the symbol and an index
into the string table whose entry contains the specified string. (If the
string does not already exist in the string table, it is inserted.) The
meaning of this string is determined by the ABI.

The global and local directives are synonyms for the globl
and locl directives. They are provided for compatibility with other
assemblers.

globalresource

globalresource-directive ::= .globalresource expression , string
| .globalresource expression , string , string

The globalresource directive causes the assembler to add information to the
binary to indicate that there was a global port or clock declaration. The first
argument is the resource ID of the port. The second argument is the name of the
variable. The optional third argument is the tile the port was declared on. For
example:

.globalresource 0x10200, p, tile[0]

specifies that the port p was declared on tile[0] and initialized with the resource ID 0x10200.

typestring

The typestring adds an SHT_TYPEINFO entry in the ELF-extended type
section which contains the symbol and an index into the string table whose entry
contains the specified string. (If the string does not already exist in the
string table, it is inserted.) The meaning of this string is determined by the
ABI.

typestring-directive ::= .typestring symbol , string

ident, core, corerev

Each of these directives creates an ELF note section named
.xmos_note.”

info-directive ::= .ident string
| .core string
| .corerev string

The contents of this section is a (name, type, value) triplet: the name
is xmos; the type is either IDENT, CORE or COREREV; and
the value is the specified string.

section, pushsection, popsection

The section directives change the current ELF section (see Sections and Relocations
).

section-directive ::= sec-or-push name
| sec-or-push name , flags sec-typeopt
| .popsection
sec-or-push ::= .section
| .pushsection
flags ::= string
sec-type ::= type
| type , flag-args
type ::= @progbits
| @nobits
flag-args ::= string

The code following a section or pushsection directive is
assembled and appended to the named section. The optional flags may
contain any combination of the following characters.

a

section is allocatable

c

section is placed in the global constant pool

d

section is placed in the global data region

w

section is writable

x

section is executable

M

section is mergeable

S

section contains zero terminated strings

The optional type argument progbits specifies that the section
contains data; nobits specifies that it does not.

If the M symbol is specified as a flag, a type argument must be
specified and an integer must be provided as a flag-specific argument.
The flag-specific argument represents the entity size of data entries in
the section. For example:

.section .cp.const4, "M", @progbits, 4

Sections with the M flag but not S flag must contain fixed-size
constants, each flag-args bytes long. Sections with both the M and
S flags must contain zero-terminated strings, each character
flag-args bytes long. The linker may remove duplicates within sections
with the same name, entity size and flags.

Each section with the same name must have the same type and flags. The
section directive replaces the current section with the named
section. The pushsection directive pushes the current section onto
the top of a section stack and then replaces the current section with
the named section. The popsection directive replaces the current
section with the section on top of the section stack and then pops this
section from the stack.

text

The text directive changes the current ELF section to the .text
section. The section type and attributes are determined by the ABI.

text-directive ::= .text

set, linkset

A symbol is assigned a value using the set or linkset directive.

set-directive ::= set-type symbol , expression
set-type ::= .set
| .linkset

The set directive defines the named symbol with the value of the
expression. The expression must be either a constant or a symbol: if the
expression is a constant, the symbol is defined in the absolute section;
if the expression is a symbol, the defined symbol inherits its section
information and other attributes from this symbol.

The linkset directive is the same, except that the expression is not
evaluated; instead one or more SHT_EXPR entries are created in the
ELF-extended expression section which together form a tree
representation of the expression.

Any symbol used in the assembly code may be a target of an SHT_EXPR
entry, in which case its value is computed by the linker by evaluating
the expression once values for all other symbols in the expression are
known. This may happen at any incremental link stage; once the value is
known, it is assigned to the symbol as with set and the expression entry
is eliminated from the linked object.

cc_top, cc_bottom

The cc_top and cc_bottom directives are used to mark the
beginning and end of elimination blocks.

cc-top-directive ::= .cc_top name , predicate
| .cc_top name
cc-directive ::= cc-top-directive
| .cc_bottom name
name ::= symbol
predicate ::= symbol

cc_top and cc_bottom directives with the same name refer to the
same elimination block. An elimination block must have precisely one
cc_top directive and one cc_bottom directive. The top and bottom
of an elimination block must be in the same section. The elimination
block consists of the data and labels in this section between the
cc_top and cc_bottom directives. Elimination blocks must be
disjoint; it is illegal for elimination blocks to overlap.

An elimination block is retained in final executable if one of the following
is true:

  • A label inside the elimination block is referenced from a location
    outside an elimination block.
  • A label inside the elimination block is referenced from an elimination
    block which is not eliminated
  • The predicate symbol is defined outside an elimination block or
    is contained in an elimination block which is not eliminated.

If none of these conditions are true the elimination block is removed from
the final executable.

scheduling

The scheduling directive enables or disables instruction scheduling.
When scheduling is enabled, the assembler may reorder instructions to
minimize the number of FNOPs. The default scheduling mode is determined
by the command-line option -fschedule
.

scheduling-directive ::= .scheduling scheduling-mode
scheduling-mode ::= on
| off
| default

issue_mode

The issue_mode directive changes the current issue mode assumed by the
assembler. See Instructions
for details of how the issue mode
affects how instructions are assembled.

issue-mode-directive ::= issue_mode issue-mode
issue-mode ::= single
| dual

syntax

The syntax directive changes the current syntax mode. See
Instructions
for details of how assembly instructions
are specified in each mode.

syntax-directive ::= .syntax syntax
syntax ::= default
| architectural

assert

assert-directive ::= .assert constant , symbol , string

The assert directive requires an assertion to be tested prior to
generating an executable object: the assertion fails if the symbol has a
non-zero value. If the constant is 0, a failure should be reported as a
warning; if the constant is 1, a failure should be reported as an error.
The string is a message for an assembler or linker to emit on failure.

Overlay Directives

The overlay directives control how code and data is partitioned into overlays
that are loaded on demand at runtime.

overlay-directive ::= .overlay_reference symbol , symbol
| .overlay_root symbol , symbol
| .overlay_root symbol
| .overlay_subgraph_conflict sym-list
sym-list ::= sym-list , symbol
| symbol
  • The overlay_root directive specifies that the first symbol should be
    treated as an overlay root. The optional second symbols specifies a overlay
    key symbol. If no overlay key symbol is explictly specified the overlay root
    symbol is used as the key symbol. Specifying the same overlay key symbol for
    multiple overlay roots forces the overlay roots into the same overlay.
  • The overlay_reference directive specifies that linker should assume that
    there is a reference from the first symbol to the second symbol when
    it partitions the program into overlays.
  • The overlay_subgraph_conflict directive specifies that linker should not
    place any code or data reachable from one the symbols into an overlay that is
    mapped an overlay region that contains another overlay containing code or data
    reachable from one of the other symbols.

Language Directives

The language directives create entries in the ELF-extended expression
section; the encoding is determined by the ABI.

xc-directive ::= globdir symbol , string
| globdir symbol , symbol , range-args , string
| .globpassesref symbol , symbol , string
| .call symbol , symbol
| .par symbol , symbol , string
range-args ::= expression , expression
globdir ::= .globread
| .globwrite
| .parwrite
| .globpassesref

For each directive, the string is an error message for the assembler or
linker to display on encountering an error attributed to the directive.

call

Both symbols must have function type. This directive sets the property that
the first function may make a call to the second function.

par

Both symbols must have function type. This directive sets the property
that the first function is invoked in parallel with the second function.

globread

The first symbol must have function type and the second directive must
have object type. This directive sets the property that the function may
read the object. When a range is specified, the first expression is the
offset from the start of the variable in bytes of the address which is
read and the second expression is the size of the read in bytes.

globwrite

The first symbol must have function type and the second directive must
have object type. This directive sets the property that the function may
write the object. When a range is specified, the first expression is the
offset from the start of the variable in bytes of the address which is
written and the second expression is the size of the write in bytes.

parwrite

The first symbol must have function type and the second directive must have
object type. This directive set the property that the function is called in
an expression which writes to the object where the order of evalulation of
the write and the function call is undefined. When a range is specified, the
first expression is the offset from the start of the variable in bytes of
the address which is written and the second expression is the size of the
write in bytes.

globpassesref

The first symbol must have function type and the second directive must have
object type. This directive sets the property that the object may be passed
by reference to the function.

XMOS Timing Analyzer Directives

The XMOS Timing Analyzer directives add timing metadata to ELF sections.

xta-directive ::= .xtabranch exp-listopt
| .xtaendpoint string , source-location
| .xtacall string , source-location
| .xtalabel string , source-location
| .xtathreadstart
| .xtathreadstop
| .xtaloop constant
| .xtacommand string , source-location
source-location ::= string , string , constant

The first string of a source location is the compilation directory. The
second string is the path to the file. The path may be specified as
either a relative path from the compilation directory or as an absolute
path. The third argument is the line number.

  • xtabranch specifies a comma-separated list of locations that may
    be branched to from the current location.
  • xtaendpoint marks the current location as an endpoint with the
    specified label.
  • xtacall marks the current location as a function call with the
    specified label.
  • xtalabel marks the current location using the specified label.
  • xtathreadstart apecifies that a thread may be initialized to
    start executing at the current location.
  • xtathreadstop specifies that a thread executing the instruction
    at the current location will not execute any further instructions.
  • xtaloop specifies that the innermost loop containing the current
    location executes the specified number of times.
  • xtacommand specifies an XTA command to be executed when analyzing
    the executable.

uleb128, sleb128

The following directives emit, for each expression in the
comma-separated list of expressions, a value that encodes either an
unsigned or signed DWARF little-endian base 128 number.

leb-directive ::= .uleb128 exp-list
| .sleb128 exp-list

space, skip

The space directive emits a sequence of bytes, specified by the
first expression, each with the fill value specified by the second
expression. Both expressions must be constant expressions.

space-or-skip ::= .space
| .skip
space-directive ::= space-or-skip expression
| space-or-skip expression , expression

The skip directive is a synonym for the space directive. It is
provided for compatibility with other assemblers.

type

The type directive specifies the type of a symbol to be either a
function symbol or an object symbol.

type-directive ::= .type symbol , symbol-type
symbol-type ::= @function
| @object

size

The size directive specifies the size associated with a symbol.

size-directive ::= .size symbol , expression

jmptable, jmptable32

The jmptable and jmptable32 directives generate a table of
unconditional branch instructions. The target of each branch instruction
is the next label in the list. The size of the each branch instruction
is 16 bits for the jmptable directive and 32 bits for the
jmptable32 directive.

jmptable-directive ::= .jmptable jmptable-listopt
| .jmptable32 jmptable-listopt
jmptable-list ::= symbol
| jmptable-list symbol

Each symbol must be a label. A maximum of 32 labels maybe specified. If
the unconditional branch distance does not fit into a 16-bit branch
instruction, a branch is made to a trampoline at the end of the table,
which performs the branch to the target label.

Instructions

Assembly instructions are normally inserted into an ELF text section.
The syntax of an instruction is:

instruction ::= mnemonic instruction-argsopt
instruction-args ::= instruction-args , instruction-arg
| instruction-arg
instruction-arg ::= symbol [ expression ]
| symbol [ expression ] : symbol
| expression

To target the dual issue execution mode of xCORE-200 devices, instructions may
be put in bundles:

separator ::= newline
| ;
instruction-bundle ::= { ⟨separator⟩* bundle-contents ⟨separator⟩* }
bundle-contents ::= instruction ⟨separator⟩+ instruction
| instruction

The current issue mode, as specifed by the issue_mode directive
(see issue_mode
), affects how the assembler assembles
instructions. Initially the current issue mode is single and instruction bundles
cannot be used. If the current issue mode is changed to dual then:

  • Instruction bundles can be specified.
  • 16-bit instructions not in an instruction bundle are implicitly
    placed in an instruction bundle alongside a NOP instruction.
  • The encoding of some operands may change. For example the assembler
    applies a different scaling factor to the immediate operand of relative
    branch instructions to match the different scaling factor that the processor
    uses at runtime when the instruction is executed in dual issue mode.

The order in which instructions are listed in an instruction bundle is not
significant. The assembler may reorder the instructions in the bundle to satisfy
architectural constraints.

The assembly instructions are summarized below using the default assembly
syntax. The architecture manual
documents the architectural
syntax of the instructions. The syntax directive is used to switch the syntax
mode.

The following notation is used:

bitp

one of: 1, 2, 3, 4, 5, 6, 7, 8, 16, 24 and

Assembly Programming Manual Read More »

Add support for a new flash device

To support a new flash device, a configuration file must be written that
describes the device characteristics, such as page size, number of pages
and commands for reading, writing and erasing data. This information can
be found in the datasheet for the flash device. Many devices available
in the market can be described using these configuration parameters;
those that cannot are unsupported.

The configuration file for the Numonyx
M25P10-A

is shown
below. The device is described as an initializer for a C
structure, the values of which are described in the following sections.

10,                     /* 1.  libflash device ID */
256,                    /* 2.  Page size */
512,                    /* 3.  Number of pages */
3,                      /* 4.  Address size */
4,                      /* 5.  Clock divider */
0x9f,                   /* 6.  RDID cmd */
0,                      /* 7.  RDID dummy bytes */
3,                      /* 8.  RDID data size in bytes */
0x202011,               /* 9.  RDID manufacturer ID */
0xD8,                   /* 10. SE cmd */
0,                      /* 11. SE full sector erase */
0x06,                   /* 12. WREN cmd */
0x04,                   /* 13. WRDI cmd */
PROT_TYPE_SR,           /* 14. Protection type */
{{0x0c,0x0},{0,0}},     /* 15. SR protect and unprotect cmds */
0x02,                   /* 16. PP cmd */
0x0b,                   /* 17. READ cmd */
1,                      /* 18. READ dummy bytes*/
SECTOR_LAYOUT_REGULAR,  /* 19. Sector layout */
{32768,{0,{0}}},        /* 20. Sector sizes */
0x05,                   /* 21. RDSR cmd*/
0x01,                   /* 22. WRSR cmd */
0x01,                   /* 23. WIP bit mask */

Libflash Device ID

10, /* 1. libflash device ID */

This value is returned by libflash on a call to the function fl_getFlashType so that
the application can identify the connected flash device.

Page Size and Number of Pages

10,                     /* 1.  libflash device ID */
256,                    /* 2.  Page size */

These values specify the size of each page in bytes and the total number
of pages across all available sectors. On the M25P10-A datasheet, these
can be found from the following paragraph on page 6:

The memory is organized as 4 sectors, each containing 128 pages.
Each page is 256 bytes wide. Thus, the whole memory can be viewed as
consisting of 512 pages, or 131,072 bytes.

Address Size

3,                      /* 4.  Address size */

This value specifies the number of bytes used to represent an address.
the table below reproduces the part of the M25P10-A
datasheet that provides this information. In the table, all instructions
that require an address take three bytes.

Table 4 on page 17 of M25P10-A datasheet

Instruction

Description

One-byte instruction code

Address byte

Dummy bytes

Data bytes

WREN

Write Enable

0000 0110

06h

0

0

0

WRDI

Write Disable

0000 0100

04h

0

0

0

RDID

Read

1001 1111

9Fh

0

0

1 to 3

RDSR

Read Status Register

0000 0101

05h

0

0

1 to ∞

WRSR

Write Status Register

0000 0001

01h

0

0

1

READ

Read Data Bytes

0000 0011

03h

3

0

1 to ∞

FAST_READ

Read Data Bytes at Higher Speed

0000 1011

0Bh

3

1

1 to ∞

PP

Page Program

0000 0010

02h

3

0

1 to 256

SE

Sector Erase

1101 1000

D8h

3

0

0

BE

Bulk Erase

1100 0111

C7h

0

0

0

DP

Deep Power-down

1011 1001

B9h

0

0

0

RES

Release from Deep Power-down, and Read Electronic Signature

1010 1011

ABh

0

3

1 to ∞

Release from Deep Power-down

0

0

0

Clock Rate

4,                      /* 5.  Clock divider */

This value is used to determine the clock rate for interfacing with the
SPI device. For a value of n, the SPI clock rate used is 100/2*n MHz.
libflash supports a maximum of 12.5MHz.

The table below reproduces the part of the M25P10-A
datasheet that provides this information. The AC characteristics table
shows that all instructions used in the configuration file, as discussed
throughout this document, can operate at up to 25MHz. This is faster than
libflash can support, so the value 4 is provided to generate a 12.5MHz clock.

Table 18 on page 40 of M25P10-A datasheet (first four entries only).

Symbol

Alt.

Parameter

Min

Typ

Max

Unit

fC

fC

Clock frequency for the following instructions: FAST_READ, PP, SE, BE, DP, RES, WREN, WRDI, RDSR, WRSR

D.C.

 

25

MHz

fR

 

Clock frequency for READ instructions

D.C.

 

20

MHz

tCH

tCLH

Clock High time

18

   

ns

tCL

tCLL

Clock Low time

18

   

ns

In general, if the SPI device supports different clock rates for
different commands used by libflash, the lowest value must be specified.

Read Device ID

0x9f,                   /* 6.  RDID cmd */
0,                      /* 7.  RDID dummy bytes */
3,                      /* 8.  RDID data size in bytes */
0x202011,               /* 9.  RDID manufacturer ID */

Most flash devices have a hardware identifier that can be used to
identify the device. This is used by libflash when one or more flash
devices are supported by the application to determine which type of
device is connected. The sequence for reading a device ID is typically
to issue an RDID (read ID) command, wait for zero or more dummy bytes,
and then read one or more bytes of data.

Table 4 on page 17 of M25P10-A datasheet
reproduces the part of the
M25P10-A datasheet that provides this information. The row for the
instruction RDID shows that the command value is 0x9f, that there
are no dummy bytes, and one to three data bytes. As shown in
Table 5 on page 19 of M25P10-A datasheet
and Figure 9 on page 19 of M25P10-A datasheet
,
the amount of data read depends on whether just the manufacturer ID
(first byte) is required, or whether both the manufacturer ID and the
device ID (second and third bytes) are required. All three bytes are
needed to uniquely identify the device, so the manufacturer ID is
specified as the three-byte value 0x202011.

Table 5 on page 19 of M25P10-A datasheet

Manufacturer identification

Device identification

Memory type

Memory capacity

20h

20h

11h

Figure 9 on page 19 of M25P10-A datasheet
/files/images/14627/7/fl-m25p10a-fig9.png

In general, if there is a choice of RDID commands then the JEDEC
compliant one should be preferred. Otherwise, the one returning the
longest ID should be used.

Sector Erase

0xD8,                   /* 10. SE cmd */
0,                      /* 11. SE full sector erase */

Most flash devices provide an instruction to erase all or part of a
sector.

Table 4 on page 17 of M25P10-A datasheet
reproduces the part of the
M25P10-A datasheet that provides this information. The row for the
instruction SE shows that the command value is 0xd8. On the M25P10-A
datasheet, the amount of data erased can be found from the first
paragraph on page 28:

The Sector Erase (SE) instruction sets to ‘1’ (FFh) all bits inside
the chosen sector.

In this example the SE command erases all of the sector, so the SE data
value is set to 0. If the number of bytes erased is less than a full
sector, this value should be set to the number of bytes erased.

Write Enable/Disable

0x06,                   /* 12. WREN cmd */
0x04,                   /* 13. WRDI cmd */

Most flash devices provide instructions to enable and disable writes to
memory. Table 4 on page 17 of M25P10-A datasheet
reproduces the part
of the M25P10-A datasheet that provides this information. The row for
the instruction WREN shows that the command value is 0x06, and the
row for the instruction WRDI shows that the command value is 0x04.

Memory Protection

PROT_TYPE_SR,           /* 14. Protection type */
{{0x0c,0x0},{0,0}},     /* 15. SR protect and unprotect cmds */

Some flash devices provide additional protection of sectors when writes
are enabled. For devices that support this capability, libflash attempts
to protect the flash image from being accidentally corrupted by the
application. The supported values for protection type are:

PROT_TYPE_NONE

The device does not provide protection

PROT_TYPE_SR

The device provides protection by writing the status register

PROT_TYPE_SECS

The device provides commands to protect individual sectors

The protection details are specified as part of a construction of the
form:

{{a,b},{c,d}}

If the device does not provide protection, all values should be set to
0. If the device provides SR protection, a and b should be set to
the values to write to the SR to protect and unprotect the device, and
c and d to 0. Otherwise, c and d should be set to the values to
write to commands to protect and unprotect the device, and a and b
to 0.

Table 2 on page 13 of M25P10-A datasheet
and Table 6 on page 20 of M25P10-A datasheet

reproduce the parts of the M25P10-A datasheet that provide this information.
The first table shows that BP0 and BP1 of the status register should be set to
1 to protect all sectors, and both to 0 to disable protection. The second table
shows that these are bits 2 and 3 of the SR.

Table 2 on page 13 of M25P10-A datasheet

Status Register Content BP1 bit

Memory content BP0 bit

0

0

none

All sectors (four sectors: 0, 1, 2 and 3)

0

1

Upper quarter (sector 3)

Lower three-quarters (three sectors: 0 to 2)

1

0

Upper half (two sectors: 2 and 3)

Lower half (sectors 0 and 1)

1

1

All sectors (four sectors: 0, 1, 2 and 3)

none

Table 6 on page 20 of M25P10-A datasheet
/files/images/14627/7/fl-m25p10a-tab6.png

Programming Command

0x02,                   /* 16. PP cmd */

Devices are programmed either a page at a time or a small number of
bytes at a time. If page programming is available it should be used, as
it minimizes the amount of data transmitted over the SPI interface.

Table 4 on page 17 of M25P10-A datasheet
reproduces the part of the
M25P10-A datasheet that provides this information. In the table, a page
program command is provided and has the value 0x02.

If page programming is not supported, this value is a concatenation of
three separate values. Bits 0..7 must be set to 0. Bits 8..15 should
contain the program command. Bits 16..23 should contain the number of
bytes per command. The libflash library requires that the first program
command accepts a three byte address but subsequent program command use
auto address increment (AAI).

An example of a device without a PP command is the ESMT
F25L004A

.
the table below reproduces the part of the F25L004A
datasheet that provides this information. In the timing diagram, the AAI
command has a value 0xad, followed by a three-byte address and two
bytes of data.

Table 7 on page 12 of F25L004A datasheet.

Symbol

Parameter

Minimum

Units

TPU-READ

VDD Min to Read Operation

10

µ s

TPU-WRITE

VDD Min to Write Operation

10

µ s

The corresponding entry in the specification file is:

0x00|(0xad<<8)|(2<<16), /* No PP, have AAI for 2 bytes */

Read Data

0x0b,                   /* 17. READ cmd */
1,                      /* 18. READ dummy bytes*/

The sequence for reading data from a device is typically to issue a READ
command, wait for zero or more dummy bytes, and then read one or more
bytes of data.

Table 4 on page 17 of M25P10-A datasheet
reproduces the part of the
M25P10-A datasheet that provides this information. There are two
commands that can be used to read data: READ and FAST_READ. The row for
the instruction FAST_READ shows that the command value is 0x0b,
followed by one dummy byte.

Sector Information

SECTOR_LAYOUT_REGULAR,  /* 19. Sector layout */
{32768,{0,{0}}},        /* 20. Sector sizes */

The first value specifies whether all sectors are the same size. The
supported values are:

SECTOR_LAYOUT_REGULAR

The sectors all have the same size

SECTOR_LAYOUT_IRREGULAR

The sectors have different sizes

On the M25P10-A datasheet, this can be found from the following
paragraph on page 15:

The memory is organized as:

  • 131,072 bytes (8 bits each)
  • 4 sectors (256 Kbits, 32768 bytes each)
  • 512 pages (256 bytes each).

The sector sizes is specified as part of a construction:
{a, {b, {c}}}. For regular sector sizes, the size is specified in
a. The values of b and c should be 0.

For irregular sector sizes,
the size number of sectors is specified in b. The log base 2 of the
number of pages in each sector is specified in c. The value of a
should be 0. An example of a device with irregular sectors is the AMIC
A25L80P

.
Table 2 on page 7 of A25L80P datasheet
reproduces the part of this
datasheet that provides the sector information.

Table 2 on page 7 of A25L80P datasheet

Sector

Sector Size (Kb)

Address Range

15

64

F0000h

FFFFFh

14

64

E0000h

EFFFFh

13

64

D0000h

DFFFFh

12

64

C0000h

CFFFFh

11

64

B0000h

BFFFFh

10

64

A0000h

AFFFFh

9

64

90000h

9FFFFh

8

64

80000h

8FFFFh

7

64

70000h

7FFFFh

6

64

60000h

6FFFFh

5

64

50000h

5FFFFh

4

64

40000h

4FFFFh

3

64

30000h

3FFFFh

2

64

20000h

2FFFFh

1

64

10000h

1FFFFh

0-4

32

08000h

0FFFFh

0-3

16

04000h

07FFFh

0-2

8

02000h

03FFFh

0-1

4

01000h

01FFFh

0-0

4

00000h

00FFFh

The corresponding entry in the specification file is:

SECTOR_LAYOUT_IRREGULAR,
    {0,{20,{4,4,5,6,7,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8}}},

Status Register Bits

0x05,                   /* 21. RDSR cmd*/
0x01,                   /* 22. WRSR cmd */
0x01,                   /* 23. WIP bit mask */

Most flash devices provide instructions to read and write a status
register, including a write-in-progress bit mask.

Table 4 on page 17 of M25P10-A datasheet
reproduces the part of the
M25P10-A datasheet that documents the RDSR and WRSR commands. The
diagram in Table 6 on page 20 of M25P10-A datasheet
shows that the WIP
bit is in bit position 0 of the SR, resulting in a bit mask of 0x01.

Add Support to xTimeComposer

A configuration file can be used with libflash or xflash. The example
program below uses libflash to connect to a M25P10-A device, the
configuration parameters which are specified in m25p10a.

#include "platform.h"
#include "flash.h"
#include "flashlib.h"
#include "stdio.h"
#include "stdlib.h"

fl_PortHolderStruct SPI = {PORT_SPI_MISO,
                           PORT_SPI_SS,
                           PORT_SPI_CLK,
                           PORT_SPI_MOSI,
                           XS1_CLKBLK_1};

fl_DeviceSpec myFlashDevices[] = {
 {
   #include "m25p10a"
 }
};

int flash_access() {
  if (fl_connectToDevice(SPI, myFlashDevices,
      sizeof(myFlashDevices)/sizeof(fl_DeviceSpec)) != 0) {
    printf("No supported flash devices found.\n"); exit(1);
  } else {
  printf("Found custom flash device m25p10a.\n"); exit(0);
  }
  return 0;
}

int main() {
  // multicore main is required for xscope
  par {
    on stdcore[0] : flash_access();
  }
}

The custom flash device must be specified in the XN file as follows:

<ExternalDevices>
  <Device NodeId="0" Tile="0" Name="bootFlash"
          Class="SPIFlash" Type="M25P10A">
    <Attribute Name="PORT_SPI_MISO" Value="PORT_SPI_MISO" />
    <Attribute Name="PORT_SPI_SS" Value="PORT_SPI_SS" />
    <Attribute Name="PORT_SPI_CLK" Value="PORT_SPI_CLK" />
    <Attribute Name="PORT_SPI_MOSI" Value="PORT_SPI_MOSI" />
  </Device>
</ExternalDevices>

To compile an image file that links to the lib flash library,
start the command-line tools

and enter the following command:

xcc main.xc -o prog.xe -target=target_with_custom_flash.xn -lflash

To generate an image file in the xCORE flash format, which can be
subsequently programmed into the above flash device,
enter the following command:

xflash prog.xe -o imgfile –spi-spec m25p10a

XFLASH generates an image for the custom flash device, which it writes
to the specified image file.

Select a Flash Device

When selecting a flash device for use with an xCORE device, the following
guidelines are recommended:

  • If access to the data partition is required, select a device with
    fine-grained erase granularity, as this will minimize the gaps
    between the factory and upgrade images, and will also minimize the
    amount of data that libflash needs to buffer when writing data.
  • Select a device with sector protection if possible, to ensure that
    the bootloader and factory image are protected from accidental
    corruption post-deployment.
  • Select a flash speed grade suitable for the application. Boot times
    are minimal even at low speeds.

Documentation

Add support for a new flash device Read More »

Safeguard IP and device authenticity

xCORE devices contain on-chip one-time programmable (OTP) memory that can
be blown during or after device manufacture testing. You can program the
xCORE AES Module into the OTP of a device, allowing programs to be stored
encrypted on flash memory. This helps provide:

  • Secrecy

    Encrypted programs are hard to reverse engineer.

  • Program Authenticity

    The AES loader will not load programs that have been tampered with or
    other third-party programs.

  • Device Authenticity

    Programs encrypted with your secret keys cannot be cloned using xCORE
    devices provided by third parties.

Once the AES Module is programmed, the OTP security bits are blown,
transforming each tile into a “secure island” in which all computation,
memory access, I/O and communication are under exclusive control of the
code running on the tile. When set, these bits:

  • force boot from OTP to prevent bypassing,
  • disable JTAG access to the tile to prevent the keys being read, and
  • stop further writes to OTP to prevent updates.

The AES module provides a strong level of protection from casual
hackers. It is important to realize, however, that there is no such
thing as unbreakable security and there is nothing you can do to
completely prevent a determined and resourceful attacker from extracting
your keys.

The xCORE AES module

The xCORE AES Module authenticates and decrypts programs from SPI flash
devices. When programmed into a device, it enables the following secure
boot procedure, as illustrated in the figure below.

Secure boot procedure used with the AES Module

/files/images/14591/6/aes-boot.png

  1. The device loads the primary bootloader from its ROM, which detects
    that the secure boot bit is set in the OTP and then loads and
    executes the AES Module from OTP.
  2. The AES Module loads the flash loader into RAM over SPI.
  3. The AES Module authenticates the flash loader using the CMAC-AES-128
    algorithm and the 128-bit authentication key. If authentication
    fails, boot is halted.
  4. The AES Module places the authentication key and decryption key in
    registers and jumps to the flash loader.

The flash loader performs the following operations:

  1. Selects the image with the highest number that validates against its
    CRC.
  2. Authenticates the selected image header using its CMAC tag and
    authentication key. If the authentication fails, boot is halted.
  3. Authenticates, decrypts and loads the table of program/data segments
    into memory. If any images fail authentication, the boot halts.
  4. Starts executing the program.

For multi-node systems, the AES Module is written to the OTP of one
tile, and a secure boot-from-xConnect Link protocol is programmed into all
other tiles.

Develop with the AES module enabled

You can activate the AES Module at any time during development or device
manufacture. In a development environment, you can activate the module
but leave the security bits unset, enabling:

  • XFLASH to use the device to load programs onto flash memory,
  • XGDB to debug programs running on the device, and
  • XBURN to later write additional OTP bits to protect the device.

In a production environment, you must protect the device to prevent the
keys from being read out of OTP by the end user.

To program the AES Module into the xCORE device on your development
board, start the command-line tools

and enter the following commands:

  1. xburn –genkey keyfile

    XBURN writes two random 128-bit keys to keyfile. The first line is
    the authentication key, the second line the decryption key.

    The keys are generated using the open-source library crypto++. If you
    prefer, you can create this file and provide your own keys.

  2. xburn -l

    XBURN prints an enumerated list of all JTAG adapters connected to
    your PC and the devices on each JTAG chain, in the form:

    ID - NAME (ADAPTER-SERIAL-NUMBER)

  3. xburn –id ID –lock keyfile –target-file target.xn –enable-jtag –disable-master-lock

    XBURN writes the AES Module and security keys to the OTP memory of
    the target device and sets its secure boot bit. The SPI ports used
    for booting are taken from the XN file (see ExternalDevice
    ).

To encrypt your program and write it to flash memory, enter the command:

xflash –id ID bin.xe –key keyfile

To protect the xCORE device, preventing any further development, enter the command:

xburn –id ID –target-file target.xn –disable-jtag –lock keyfile

Production flash programming flow

In production manufacturing environments, the same program is typically
programmed into multiple SPI devices.

To generate an encrypted image in the xCORE flash format,
start the command-line tools

and enter the following command:

xflash prog.xe -key keyfile -o image-file

This image can be programmed directly into flash memory using a
third-party flash programmer, or it can be programmed using XFLASH (via
an xCORE device). To program using XFLASH, enter the following commands:

  1. xflash -l

    XFLASH prints an enumerated list of all JTAG adapters connected to
    your PC and the devices on each JTAG chain, in the form:

    ID - NAME (ADAPTER-SERIAL-NUMBER)

  2. xflash –id ID –target-file platform.xn –write-all image-file

    XFLASH generates an image in the xCORE flash format that contains a
    first stage loader and factory image comprising the binary and data
    segments from your compiled program. It then writes this image to
    flash memory using the xCORE device.

The XN file must define an SPI flash device and specify the four ports
of the xCORE device to which it is connected (see ExternalDevice
).

Production OTP programming flow

In production manufacturing environments, the same keys are typically
programmed into multiple xCORE devices.

To generate an image that contains the AES Module and security keys to
be written to the OTP, start the command-line tools

and enter the following commands:

  1. xburn –genkey keyfile

    XBURN writes two random 128-bit keys to keyfile. The first line is
    the authentication key, the second line the decryption key.

    The keys are generated using the open-source library crypto++. If you
    prefer, you can create this file and provide your own keys.

  2. xburn –target-file target.xn –lock keyfile -o aes-image.otp

    XBURN generates an image that contains the AES Module, security keys
    and the values for the security bits.

The image contains the keys and must be kept secret.

To write the AES Module and security bits to a device in a production
environment, enter the following commands:

  1. xburn -l

    XBURN prints an enumerated list of all JTAG adapters connected to the
    host and the devices on each JTAG chain, in the form:

    ID - NAME (ADAPTER-SERIAL-NUMBER)

  2. xburn –id ID –target-file target.xn aes-image.otp

    XBURN loads a program onto the device that writes the AES Module
    and security keys to the OTP, and sets its secure boot bits. XBURN
    returns 0 for success or non-zero for failure.

Documentation

Safeguard IP and device authenticity Read More »

List of devices natively supported by libflash

libflash supports a wide range of flash devices available in the market.
Each flash device is described using a SPI specification file. The table
in the table below lists the flash devices
for which SPI spec files are included with xTIMEcomposer.

Manufacturer

Part Number

Enabled in libflash by default

Altera

EPCS1

Y

AMIC

A25L016

N

 

A25L40P

N

 

A25L40PT

N

 

A25L40PUM

N

 

A25L80P

N

Atmel

AT25DF021

N

 

AT25DF041A

Y

 

AT25F512

N

 

AT25FS010

Y

ESMT

F25L004A

N

Macronix

MX25L1005C

N

NUMONYX

M25P10

N

 

M25P16

N

 

M25P40

N

 

M45P10E

N

SPANSION

S25FL204K

N

SST

SST25VF010

N

 

SST25VF016

N

 

SST25VF040

N

ST Microelectronics

M25PE10

Y

 

M25PE20

Y

Winbond

W25X10

N

 

W25X20

N

 

W25X40

Y

Documentation

List of devices natively supported by libflash Read More »

XBURN Command-Line Manual

XBURN creates OTP images, and can program these images into the OTP memory of xCORE devices.

Overall Options

The following options are used to specify the OTP image and security register contents.

  • xe-file

    Specifies bootable images to be constructed from the loadable segments from
    xe-file and a default set of security bits
    .

  • otp-file

    Specifies the OTP segments from otp-file which includes the security register value.

  • –lock keyfile

    Specifies the XCORE AES boot module
    and a
    default set of security bits
    .

  • –genkey keyfile

    Outputs to keyfile two 128-bit keys used for authentication and decrpytion. The
    keys are generated using the open-source library crypto++.

    This option is not valid with --burn or --lock.

  • –mac-address mac

    Writes a MAC address to the end of the OTP. The MAC address should be specified
    in the form 12:34:56:78:9A:BC. Multiple MAC addresses can be written by
    specifying the --mac-address option multiple times. MAC addresses are written
    to the OTP in the order the options appear.

  • –serial-number serial

    Writes a 32-bit serial number to the end of the OTP.

  • –read

    Prints the entire contents of the OTP.

  • –help

    Prints a description of the supported command-line options.

  • –version

    Displays the version number and copyrights.

Security Register Options

The following options are used to specify the contents of the OTP security register,
overriding the default options for burning XE images, OTP images and the AES module,
as given in the table below.

Default security bits written by XBURN

Security Bit

XE Image

OTP Image

AES Module (--lock)

OTP Boot

Enabled

As per OTP image file

Enabled

JTAG Access

Enabled

Disabled

Plink Access

Enabled

Enabled

Global Debug

Enabled

Disabled

Master Lock

Disabled

Enabled

  • –enable-otp-boot

    Enables boot from OTP.

  • –disable-jtag

    Disables JTAG access. Once disabled, it is not possible to gain debug access to the
    device or to read the OTP.

    This option does not disable boundary scan.

  • Disables access to the plink registers from other tiles. Disabling plink access
    restricts all access of the registers of each plinks to the tile local to that plink.

  • –disable-global-debug

    Prevents the device from participating in global debug. Disabling global debug
    prevents the tiles from entering debug using the global debug pin.

  • –enable-master-lock

    Enables the OTP master lock. No further modification of the OTP is permitted.

Target Options

The following options are used to specify the target hardware platform.

  • –list-devices

    -l

    Prints an enumerated list of all JTAG adapters connected to the
    host and the devices on each JTAG chain, in the form:

    ID - NAME    (ADAPTER-SERIAL-NUMBER)

    The adapters are ordered by their serial numbers.

  • –id ID

    Specifies the adapter connected to the target hardware.

  • –adapter-id ADAPTER-SERIAL-NUMBER

    Specifies the serial number of the adapter connected to the target hardware.

  • –jtag-speed n

    Sets the divider for the JTAG clock to n. The corresponding JTAG clock speed is
    6/(n+1)MHz. The default value is 0 (6MHz).

  • –spi-div n

    Sets the divider used in the AES Module for the SPI clock to n. The corresponding
    SPI clock speed is set to 100/(2n) MHz. The deafult value is 20 (2.5MHz).

    This option is only valid with --lock.

  • –target-file xn-file

    Specifies xn-file as the target platform.

  • –target platform

    Specifies a target platform. The platform configuration must be specified in the file
    platform.xn, which is searched for in the paths specified by the XCC_DEVICE_PATH
    environment variable (see XCC_DEVICE_PATH
    ).

Programming Options

By default, XBURN writes the specified OTP images to the target platform.

  • -o otp-file

    Place output in otp-file, disabling programming.

  • –make-exec xe-file

    Place an executable in xe-file that when run on an xCORE device performs the
    specified OTP burning operation; disables programming.

    The XE file can be run later using XRUN.

  • –force

    -f

    Do not prompt before writing the OTP. This is not default.

  • –size-limit n

    Limits the amounts of OTP memory written to the first n bytes of the OTP.
    If the image doesn’t fit within the specified limit an error will be given.

Documentation

XBURN Command-Line Manual Read More »

XSIM Command-Line Manual

XSIM performs a cycle-based simulation of an XMOS Executable (XE) file.
The XE file contains a description of the target hardware.

Overall Options

  • xe-file

    Specifies an XE file to simulate.

  • --max-cycles n

    Exits when n system cycles is reached.

  • --plugin name args

    Loads a plugin DLL. The format of args is determined by the plugin;
    if args contains any spaces, it must be enclosed in quotes.

  • --stats

    On exit, prints the following:

    • A breakdown of the instruction counts for each logical core.
    • The number of data and control tokens sent through the switches.
  • --help

    Prints a description of the supported command line options.

  • --version

    Displays the version number and copyrights.

Warning Options

  • --warn-resources

    Prints (on standard error) warning messages for the following:

    • A timed input or output operation specifies a time in the past.
    • The data in a buffered port’s transfer register is overwritten
      before it is input by the processor.

  • --warn-stack

    Turns on warnings about possible stack corruption.

    XSIM prints a warning if one XC task attempts to read
    or write to another task’s workspace. This can happen if the stack
    space for a task is specified using either #pragma stackfunction

    or #pragma stackcalls
    .

  • --no-warn-registers

    Don’t warn when a register is read before being written.

Tracing Options

Trace output for XS1 processors
Core Core State Address Instruction Mem Cycle
Name
from
XN
I0 I1 I2 S0S1(T0) … S0S1(Tn) . M S K N PC ( sym + offset) : name operands address @val

D
*
P

d

a
A
i
I
p
m
s
w

i
e
n status pairs  
m

s

k

n
    val
rm(val)
res[id]
L[adr]
S[adr]
 
I0: – No debug interrupt S1: – Interrupts and events disabled
I0: D Instruction caused debug interrupt S1: b Interrupts and events enabled
I1: * Instruction excepted S1: i Interrupts enabled and events disabled
I1: P Instruction paused S1: e Interrupts disabled and events enabled
I2: – Not in debug mode M: – MSYNC not set
I2: d Tile in debug mode M: m MSYNC set
S0: – Core not in use S: – SSYNC not set
S0: a Core active S: s SSYNC set
S0: A Core active (traced instruction belongs to this core) K: – INK not set
S0: i Core active with ININT bit set K: k INK set
S0: I Core active with ININT bit set (belongs to this core) N: – INENB not set
S0: p Core paused due to instruction fetch N: n INENB set
S0: m Core paused with MSYNC bit set rn (val) Value of register n
S0: s Core paused withSSYNC bit set res[id] Resource identifier
S0: w Core paused with WAITING bit set L/S[adr] Load from/Store to address

  • --trace-to file

    Turns on instruction tracing for all tiles. The trace is output to
    file.

  • --disable-rom-tracing

    Turns off tracing for all instructions executed from ROM.

  • --enable-fnop-tracing

    Turns on tracing of FNOP instructions.

  • --vcd-tracing args

    Enables signal tracing. The trace data is output in the standard VCD
    file format.

    If args contains any spaces, it must be enclosed in quotes. Its
    format is:

    global-optionsopt < -tile name <trace-options*>*>

    The global options are:

    • -pads

      Turns on pad tracing.

    • -o file

      Places output in file.

    The trace options are specific to the tile associated with the XN
    core declaration name, for example tile[0].

    The trace options are:

    • -ports

      Turns on port tracing.

    • -ports-detailed

      Turns on more detailed port tracing.

    • -cycles

      Turns on clock cycle tracing.

    • -clock-blocks

      Turns on clock block tracing.

    • -cores

      Turns on logical core tracing.

    • -instructions

      Turns on instruction tracing.

    To output traces from different nodes, tiles or logical cores to different
    files, this option can be specified multiple times.

    For example, the following command configures the simulator to trace
    the ports on tile[0] to the file trace.vcd.

    xsim a.xe –vcd-tracing “-o trace.vcd -start-disabled -tile tile[0] -ports”

    Tracing by the VCD plugin can be enabled and disabled using the
    _traceStart() and _traceStop() syscalls. The -start-disabled argument disables
    the vcd tracing from the start, allowing the user to enable/disable only those sections
    of code where tracing is desired. For example:

    #include <xs1.h>
    #include <syscall.h>
    
    port p1 = XS1_PORT_1A;
    
    int main() {
       p1 <: 1;
       p1 <: 0;
    
       _traceStart();
       p1 <: 1;
       p1 <: 0;
       _traceStop();
    
       p1 <: 1;
       p1 <: 0;
    
       return 0;
    }
    

Loopback Plugin Options

The XMOS Loopback plugin configures any two ports on the target platform
to be connected together. The format of the arguments to the plugin are:

  • -pin package pin

    Specifies the pin by its name on a package datasheet. The value of
    package must match the Id attribute of a Package node

    in the XN file used to compile the program.

  • -port name n offset

    Specifies n pins that correspond to a named port.

    The value of name must match the Name attribute of a
    Port node

    in the XN file used to compile the program.

    Setting offset to a non-zero value specifies a subset of the
    available pins.

  • -port tile p n offset

    Specifies n pins that are connected to the port p on a tile.

    The value of tile must match the Reference attribute of a
    Tile node
    in the XN file used to compile the program.

    p can be any of the port identifiers defined in <xs1.h>. Setting
    offset to a non-zero value specifies a subset of the available pins.

The plugin options are specified in pairs, one for each end of the
connection. For example, the following command configures the simulator
to loopback the pin connected to port XS1_PORT_1A on tile[0]
to the pin defined by the port UART_TX in the program.

xsim uart.xe –plugin LoopbackPort.dll ‘-port tile[0] XS1_PORT_1A 1 0 -port UART_TX 1 0’

xSCOPE Options

  • --xscope args

    Enables xSCOPE.
    file format.

    If args contains any spaces, it must be enclosed in quotes.
    One of the following 2 options is mandatory:

    • -offline <filename>

      Runs with xSCOPE in offline mode, placing the xSCOPE output in the given file.

    • -realtime <URL:port>

      Runs with xSCOPE in realtime mode, sending the xSCOPE output in the given URL:port.

    The following argument is optional:

    • -limit <num records>

      Limts the xSCOPE output records to the given number.

For example, the following will run xsim with xSCOPE enabled in offline mode:

xsim app.xe –xscope “-offline xscope.xmt”

For example, the following will run xsim with xSCOPE enabled in reatime mode:

xsim app.xe –xscope “-realtime localhost:12345”

XSIM Command-Line Manual Read More »

DFU loader for XMOS USB AUDIO devices

The DFU loader is a flash device firmware upgrade mechanism. To work correctly
your development board must contain the latest DFU enabled firmware.

The firmware upgrade for XMOS USB devices implementation uses the USB standard
DFU device class mechanism and is based on the following specification:
http://www.usb.org/developers/devclass_docs/DFU_1.1.pdf

Supported functionality:

  • Download of new firmware to device
  • Upload of existing firmware from device
  • Revert device back to factory image
  • Automatic reboot of device on firmware upgrade

You must use XMOS Development Tools version 10.4.1 (or later).

The DFU device on Windows requires the Theyscon USB Audio 2.0 Windows driver
version 1.13.3 or later.

Installing the factory image to the device

The DFU device interface is enabled by default in the XMOS USB Audio framework
(see devicedefines.h), and explicitly enabled in each reference design
by the following line included in the customdefines.h file of each
application:

#define DFU                (1)

Use the XMOS Development Tools to run the command:

xflash --boot-partition-size 0x30000 --factory usb_audio.xe

Where the size passed using the --boot-partition-size n argument specifies
in bytes the minimum size required to store the boot loader, factory image and
any upgrade images.

The following can be used as a guide to help calculate the required boot
partition size for a design:

  • boot partition size = loader size + maximum size of factory image +
    maximum size of upgrade images + padding to sector boundaries

Where:

  • loader size = 0x1000 bytes, or 0x4000 bytes if secure boot functionality is
    used (for tools version 13.1.0 and older)
  • maximum size of factory image = number of xCORE tiles *
    xCORE SRAM size
  • maximum size of upgrade images = (number of xCORE tiles *
    xCORE SRAM size) * number of images to be held in flash concurrently

The above example sets the boot partition to a size appropriate for designs
based on a single xCORE tile, where a single upgrade image is required
in flash at any one time.

This programs the factory default firmware image into the flash device.
The device will now support the DFU mechanism, and can use it to safely receive
firmware updates, as well as revert to the factory firmware image when required,
such as in the event of a failed upgrade attempt.

Creating the upgrade image

To use the firmware upgrade mechanism you need to build a firmware upgrade
image:

  1. Edit the customdefines.h file of the application for the hardware in use,
    and change the Device Version Number by defining BCD_DEVICE.
  2. Rebuild the application.

To generate the firmware upgrade image run the following command:

xflash --factory-version 13 --upgrade 1 usb_audio.xe -o new_firmware.bin

Where the tools version passed using the --factory-version version
argument specifies the version of the tools used to create the factory image.
This should be passed as 12 for images created using tools versions 10, 11
and 12.

The --upgrade id xe-file [size] argument specifies xe-file as an upgrade
image with version id. Each version number must be a unique number greater
than 0.

You should now have the file new_firmware.bin which contains the
firmware with the newly specified Device Version Number.

For further details of the DFU features included in the XMOS USB Audio
framework and their configuration please see the Device Firmware Upgrade (DFU)

and the Configuration Defines
sections of the USB Audio Design
Guide.

For further details on the use of XFLASH to create factory and upgrade firmware
images please see the XFLASH Command-Line Manual section of the
xTIMEcomposer User Guide
.

Thesycon provide both GUI and CLI DFU tools, TUSBAudioDfu.exe and dfucons.exe
respectively. The use of the GUI tool is not covered by this document.

The correct installation of the Thesycon driver and DFU tools exceeds
the scope of this document.

Set up the image loader

Run the DFU console tool (dfucons.exe) from the Thesycon install folder,
in a Command Prompt by navigating to:

C:\Program Files\Thesycon\TUSBAudio_Driver\

To check the device has been detected, run the following command in the DFU
console:

dfucons info

The console shows the DFU devices that have been detected.

Download new firmware

To program the new firmware run the command:

dfucons download new_firmware.bin

Note that once this is done the device restarts. The original factory default
application is still present but the device is now running the upgraded
application firmware.

You can check the device has been updated by running the command:

dfucons info

This will display the device revision.

Uploading existing firmware from the device

You can retrieve a firmware image from the device, providing an upgrade image is
present.
Run the command:

dfucons upload currentfirmware.bin

The file currentfirmware.bin contains the latest upgrade image. This file is
an exact copy of the data from the flash and can be downloaded to the device
again to test.

Reverting firmware to factory image

To revert the device back to its factory (i.e XFLASH) installed state from the
new firmware, run the command:

dfucons revertfactory

The device will now be running, and only contain the factory firmware, which can
be seen by checking the device version once more.

For further details on the use of the Thesycon DFU tools please see
Thesycon USB Audio 2.0 Driver for Windows User Manual
.

The XMOS DFU loader is provided as source as part of the XMOS USB Audio software
framework, see Building the XMOS DFU loader – OS X
.

Set up the image loader

  1. Open a terminal
  2. Change directory to where the loader has been built
  3. Run the command:

    source setup.sh

Download new firmware

To program the new firmware run the command:

./xmosdfu --download new_firmware.bin

Note that once this is done the device restarts. The original factory default
application is still present but the device is now running the upgraded
application firmware.

Uploading existing firmware from the device

You can retrieve a firmware image from the device, providing an upgrade image is
present.

Run the command:

./xmosdfu --upload currentfirmware.bin

The file currentfirmware.bin contains the latest upgrade image. This file is
an exact copy of the data from the flash and can be downloaded to the device
again to test.

Reverting firmware to factory image

To revert the device back to its factory (i.e XFLASH) installed state from the
new firmware, run the command:

./xmosdfu --revertfactory

The device will now be running, and only contain the factory firmware.

The XMOS DFU loader is provided as source as part of the USB Audio
framework, located in sc_usb_audio/module_dfu/host/xmos_dfu_osx.

The loader is compiled using libusb, the code for the loader is contained in the
file xmosdfu.cpp

To build the loader a Makefile is provided, which can be run as follows:

make -f Makefile.OSX all

This Makefile contains the following:

all:
	g++ -g -o xmosdfu xmosdfu.cpp -I. -IOSX libusb-1.0.0.dylib -m32

DFU loader for XMOS USB AUDIO devices Read More »

XMOS USB Device (XUD) Library

This document details the XMOS USB Device (XUD) Library. This library
enables the development of USB 2.0 devices on the XMOS xCORE architecture.

This document describes the structure of the library, its basic use
and resources required.

This document assumes familiarity with the XMOS xCORE architecture, the
Universal Serial Bus 2.0 Specification (and related specifications),
the XMOS tool chain and XC language.

The XUD library allows the implementation of both full-speed and
high-speed USB 2.0 devices on L-Series, G-series and U-Series devices.

For the L and G series the implementation requires the use of an
external ULPI transceiver such as the SMSC USB33XX range. U-Series
devices include an integrated USB transceiver. Three libraries, with
identical API, are provided – one each for L, G and U-Series
devices.

Please note, G-series is not recommended for new designs.

The library performs all the low-level I/O operations required to meet
the USB 2.0 specification. This processing goes up to and includes the
transaction level. It removes all low-level timing requirements from the
application, allowing quick development of all manner of USB devices.

The XUD library runs in a single core with endpoint and application
cores communicating with it via a combination of channel communication
and shared memory variables.

One channel is required per IN or OUT endpoint. Endpoint 0 (the control
endpoint) requires two channels, one for each direction. Please note that
throughout this document the USB nomenclature is used: an OUT endpoint
is used to transfer data from the host to the device, an IN endpoint is
used when the host requests data from the device.

An example task diagram is shown in XUD Overview
. Circles
represent cores running with arrows depicting communication
channels between these cores. In this configuration there is one
core that deals with endpoint 0, which has both the input and output
channel for endpoint 0. IN endpoint 1 is dealt with by a second core,
and OUT endpoint 2 and IN endpoint 5 are dealt with by a third core.
Cores must be ready to communicate with the XUD library whenever the
host demands its attention. If not, the XUD library will NAK.

It is important to note that, for performance reasons, cores
communicate with the XUD library using both XC channels and shared
memory communication. Therefore, all cores using the XUD library must
be on the same tile as the library itself
.

XUD Overview

The following list gives a brief description of the files that make up
the XUD layer:

include/xud.h

User defines and functions for the XUD library.

lib/xs1b/libxud_l.a

Library for L-Series devices.

lib/xs1b/libxud_u.a

Library for U-Series devices.

lib/xs1b/libxud_g.a

Library for G-Series devices.

src/XUD_EpFunctions.xc

User functions that control the XUD library.

src/XUD_EpFuncs.S

Assembler stubs of access functions.

src/XUD_Ports.xc

Definition of port mapping.

The XUD library requires the resources described in the following
sections.

Ports/Pins

G/L-Series

The ports used for the physical connection to the external ULPI transceiver must
be connected as shown in the table below.

ULPI required pin/port connections

Pin 1b

Port 4b

Signal 8b

X0D12

P1E0

 

ULPI_STP

X0D13

P1F0

 

ULPI_NXT

X0D14

 

P4C0

P8B0

ULPI_DATA[7:0]

X0D15

P4C1

P8B1

X0D16

P4D0

P8B2

X0D17

P4D1

P8B3

X0D18

P4D2

P8B4

X0D19

P4D3

P8B5

X0D20

P4C2

P8B6

X0D21

P4C3

P8B7

X0D22

P1G0

 

ULPI_DIR

X0D23

P1H0

 

ULPI_CLK

X0D24

P1I0

 

ULPI_RST_N

In addition some ports are used internally when the XUD library is in
operation. For example pins X0D2-X0D9, X0D26-X0D33 and X0D37-X0D43 on
an XS1-L device should not be used.

Please refer to the device datasheet for further information on which ports
are available.

U-Series

The U-Series of devices have an integrated USB transceiver. Some ports
are used to communicate with the USB transceiver inside the U-Series packages.
These ports/pins should not be used when USB functionality is enabled.
The ports/pins are shown in the table below.

U-Series required pin/port connections

Pin 1b

Port 4b

X0D02

 

P4A0

P8A0

P16A0

P32A20

X0D03

 

P4A1

P8A1

P16A1

P32A21

X0D04

 

P4B0

P8A2

P16A2

P32A22

X0D05

 

P4B1

P8A3

P16A3

P32A23

X0D06

 

P4B2

P8A4

P16A4

P32A24

X0D07

 

P4B3

P8A5

P16A5

P32A25

X0D08

 

P4A2

P8A6

P16A6

P32A26

X0D09

 

P4A3

P8A7

P16A7

P32A27

X0D23

P1H0

 

X0D25

P1J0

 

X0D26

 

P4E0

P8C0

P16B0

 

X0D27

 

P4E1

P8C1

P16B1

 

X0D28

 

P4F0

P8C2

P16B2

 

X0D29

 

P4F1

P8C3

P16B3

 

X0D30

 

P4F2

P8C4

P16B4

 

X0D31

 

P4F3

P8C5

P16B5

 

X0D32

 

P4E2

P8C6

P16B6

 

X0D33

 

P4E3

P8C7

P16B7

 

X0D34

P1K0

 

X0D36

P1M0

 

P8D0

P16B8

 

X0D37

P1N0

 

P8C1

P16B1

 

X0D38

P1O0

 

P8C2

P16B2

 

X0D39

P1P0

 

P8C3

P16B3

 

Core Speed

Due to I/O requirements, the library requires a guaranteed MIPS rate to
ensure correct operation. This means that core count restrictions must
be observed. The XUD core must run at at least 80 MIPS.

This means that for an xCORE device running at 400MHz there should be no more
than five cores executing at any time when using the XUD. For
a 500MHz device no more than six cores shall execute at any one time
when using the XUD.

This restriction is only a requirement on the tile on which the XUD_Manager is running.
For example, the other tile on an L16 device is unaffected by this restriction.

Clock Blocks

G/L-Series

The XUD library uses one clock block (clock block 0) and configures this
clock block to be clocked by the 60MHz clock from the ULPI transceiver.
The ports it uses are in turn clocked from the clock block.

Since clock block 0 is the default for all ports when enabled it is
important that if a port is not required to be clocked from this 60MHz
clock, then it is configured to use another clock block.

U-Series

The XUD library uses two clock blocks (clock blocks 4 and 5). These are
clocked from the USB clock. Unlike the G/L devices, clock-block 0 is not
used or affected.

Timers

The XUD library allocates and uses four timers.

Memory

The XUD library requires about 9 Kbytes of memory, of which around 6 Kbytes
is code or initialized variables that must be stored in either OTP or
Flash.

This section outlines the basic usage of XUD. Basic use is termed to
mean each endpoint runs in its own dedicated core.
Multiple endpoints in a single core are possible, please see Advanced Usage.

XUD Core: XUD_Manager()

This is the main XUD task that interfaces with the USB transceiver.
It performs power-signalling/handshaking on the USB bus, and passes packets
to/from the various endpoints.

This function should be called directly from the top-level par
statement in main() to ensure that the XUD library is ready
within the 100ms allowed by the USB specification.

  • int XUD_Manager(chanend c_epOut[], int noEpOut, chanend c_epIn[], int noEpIn, chanend ?c_sof, XUD_EpType epTypeTableOut[], XUD_EpType epTypeTableIn[], out port ?p_usb_rst, clock ?clk, unsigned rstMask, XUD_BusSpeed_t desiredSpeed, XUD_PwrConfig pwrConfig)

    This performs the low-level USB I/O operations.

    Note that this needs to run in a thread with at least 80 MIPS worst case execution speed.

    Parameters

    • c_epOut

      An array of channel ends, one channel end per output endpoint (USB OUT transaction); this includes a channel to obtain requests on Endpoint 0.

    • noEpOut

      The number of output endpoints, should be at least 1 (for Endpoint 0).

    • c_epIn

      An array of channel ends, one channel end per input endpoint (USB IN transaction); this includes a channel to respond to requests on Endpoint 0.

    • noEpIn

      The number of input endpoints, should be at least 1 (for Endpoint 0).

    • c_sof

      A channel to receive SOF tokens on. This channel must be connected to a process that can receive a token once every 125 ms. If tokens are not read, the USB layer will lock up. If no SOF tokens are required null should be used for this parameter.

    • epTypeTableOut

      See epTypeTableIn.

    • epTypeTableIn

      This and epTypeTableOut are two arrays indicating the type of the endpoint. Legal types include: XUD_EPTYPE_CTL (Endpoint 0), XUD_EPTYPE_BUL (Bulk endpoint), XUD_EPTYPE_ISO (Isochronous endpoint), XUD_EPTYPE_INT (Interrupt endpoint), XUD_EPTYPE_DIS (Endpoint not used). The first array contains the endpoint types for each of the OUT endpoints, the second array contains the endpoint types for each of the IN endpoints.

    • p_usb_rst

      The port to used to connect to an external phy reset line. Should be null for U-Series.

    • clk

      The clock block to use for the p_usb_rst port – this should not be clock block 0. Should be null for U-Series.

    • rstMask

      The mask to use when taking an external phy into/out of reset. The mask is ORed into the port to disable reset, and unset when deasserting reset. Use ‘-1’ as a default mask if this port is not shared.

    • desiredSpeed

      This parameter specifies what speed the device will attempt to run at i.e. full-speed (ie 12Mbps) or high-speed (480Mbps) if supported by the host. Pass XUD_SPEED_HS if high-speed is desired or XUD_SPEED_FS if not. Low speed USB is not supported by XUD.

    • pwrConfig

      Specifies whether the device is bus or self-powered. When self-powered the XUD will monitor the VBUS line for host disconnections. This is required for compliance reasons. Valid values are XUD_PWR_SELF and XUD_PWR_BUS.

Endpoint Type Table

The endpoint type table should take an array of XUD_EpType to inform XUD
about endpoints being used. This is mainly used to indicate the transfer-type
of each endpoint (bulk, control, isochronous or interrupt) as well as
whether the endpoint wishes to be informed about bus-resets (see Status Reporting
).

Note: endpoints can also be marked as disabled.

Endpoints that are not used will NAK any traffic from the host.

PwrConfig

The PwrConfig parameter to XUD_Manager() indicates if the device is bus or self-powered.

Valid values for this parameter are XUD_PWR_SELF and XUD_PWR_BUS.

When XUD_PWR_SELF is used, XUD_Manager() monitors the VBUS input for a valid voltage and reponds appropriately. The USB Specification states that the devices pull-ups must be disabled when a valid VBUS is not present. This is important when submitting a device for compliance testing since this is explicitly tested.

If the device is bus-powered XUD_PWR_SELF can be used since is assumed that the device is not powered up when VBUS is not present and therefore no voltage monitoring is required. In this configuration the VBUS input to the device/PHY need not be present.

XUD_PWR_BUS can be used in order to run on a self-powered board without provision for VBUS wiring to the PHY/device, but this is not advised.

Endpoint Communication with XUD_Manager()

Communication state between a core and the XUD library is encapsulated
in an opaque type:

  • XUD_ep

    Typedef for endpoint identifiers.

All client calls communicating with the XUD library pass in this type.
These data structures can be created at the start of execution of a
client core with the following call that takes as an argument the
endpoint channel connected to the XUD library:

  • XUD_ep XUD_InitEp(chanend c_ep)

    Initialises an XUD_ep.

    Parameters

    • c_ep

      Endpoint channel to be connected to the XUD library.

    Returns

    Endpoint identifier

Endpoint data is sent/received using three main functions,
XUD_SetData(), XUD_GetData() and XUD_GetSetupData().

These assembly functions implement the low-level shared memory/channel
communication with the XUD_Manager() core. For developer convenience
these calls are wrapped up by XC functions.

These functions will automatically deal with any low-level complications required
such as Packet ID toggling etc.

XUD_GetBuffer()

  • XUD_Result_t XUD_GetBuffer(XUD_ep
     ep_out, unsigned char buffer[], unsigned &length)

    This function must be called by a thread that deals with an OUT endpoint.

    When the host sends data, the low-level driver will fill the buffer. It pauses until data is available.

    Parameters

    • ep_out

      The OUT endpoint identifier (created by XUD_InitEP).

    • buffer

      The buffer in which to store data received from the host. The buffer is assumed to be word aligned.

    • length

      The number of bytes written to the buffer

    Returns

    XUD_RES_OKAY on success, for errors see Status Reporting
    .

XUD_SetBuffer()

  • XUD_Result_t XUD_SetBuffer(XUD_ep
     ep_in, unsigned char buffer[], unsigned datalength)

    This function must be called by a thread that deals with an IN endpoint.

    When the host asks for data, the low-level driver will transmit the buffer to the host.

    Parameters

    • ep_in

      The endpoint identifier (created by XUD_InitEp).

    • buffer

      The buffer of data to transmit to the host.

    • datalength

      The number of bytes in the buffer.

    Returns

    XUD_RES_OKAY on success, for errors see Status Reporting
    .

XUD_SetBuffer_EpMax()

This function provides a similar function to XUD_SetBuffer function
but it breaks the data up in packets of a fixed
maximum size. This is especially useful for control transfers where large
descriptors must be sent in typically 64 byte transactions.

  • XUD_Result_t XUD_SetBuffer_EpMax(XUD_ep
     ep_in, unsigned char buffer[], unsigned datalength, unsigned epMax)

    Similar to XUD_SetBuffer but breaks up data transfers into smaller packets.

    This function must be called by a thread that deals with an IN endpoint. When the host asks for data, the low-level driver will transmit the buffer to the host.

    Parameters

    • ep_in

      The IN endpoint identifier (created by XUD_InitEp).

    • buffer

      The buffer of data to transmit to the host.

    • datalength

      The number of bytes in the buffer.

    • epMax

      The maximum packet size in bytes.

    Returns

    XUD_RES_OKAY on success, for errors see Status Reporting
    .

XUD_DoGetRequest()

  • XUD_Result_t XUD_DoGetRequest(XUD_ep
     ep_out, XUD_ep
     ep_in, unsigned char buffer[], unsigned length, unsigned requested)

    Performs a combined XUD_SetBuffer and XUD_GetBuffer.

    It transmits the buffer of the given length over the ep_in endpoint to answer an IN request, and then waits for a 0 length Status OUT transaction on ep_out. This function is normally called to handle Get control requests to Endpoint 0.

    Parameters

    • ep_out

      The endpoint identifier that handles Endpoint 0 OUT data in the XUD manager.

    • ep_in

      The endpoint identifier that handles Endpoint 0 IN data in the XUD manager.

    • buffer

      The data to send in response to the IN transaction. Note that this data is chopped up in fragments of at most 64 bytes.

    • length

      Length of data to be sent.

    • requested

      The length that the host requested, (Typically pass the value wLength).

    Returns

    XUD_RES_OKAY on success, for errors see Status Reporting

XUD_DoSetRequestStatus()

  • XUD_Result_t XUD_DoSetRequestStatus(XUD_ep
     ep_in)

    This function sends an empty packet back on the next IN request with PID1.

    It is normally used by Endpoint 0 to acknowledge success of a control transfer.

    Parameters

    • ep_in

      The Endpoint 0 IN identifier to the XUD manager.

    Returns

    XUD_RES_OKAY on success, for errors see Status Reporting
    .

XUD_SetDevAddr()

  • XUD_Result_t XUD_SetDevAddr(unsigned addr)

    Sets the device’s address.

    This function must be called by Endpoint 0 once a setDeviceAddress request is made by the host.

    Must be run on USB core

    Parameters

    • addr

      New device address.

XUD_SetStall()

  • void XUD_SetStall(XUD_ep
     ep)

    Mark an endpoint as STALLed.

    It is cleared automatically if a SETUP received on the endpoint.

    Must be run on same tile as XUD core

    Parameters

    • ep

      XUD_ep type.

XUD_SetStallByAddr()

  • void XUD_SetStallByAddr(int epNum)

    Mark an endpoint as STALL based on its EP address.

    Cleared automatically if a SETUP received on the endpoint. Note: the IN bit of the endpoint address is used.

    Must be run on same tile as XUD core

    Parameters

    • epNum

      Endpoint number.

XUD_ClearStall()

  • void XUD_ClearStall(XUD_ep
     ep)

    Mark an endpoint as NOT STALLed.

    Must be run on same tile as XUD core

    Parameters

    • ep

      XUD_ep type.

XUD_ClearStallByAddr()

  • void XUD_ClearStallByAddr(int epNum)

    Mark an endpoint as NOT STALLed based on its EP address.

    Note: the IN bit of the endpoint address is used.

    Must be run on same tile as XUD core

    Parameters

    • epNum

      Endpoint number.

Status Reporting

Status reporting on an endpoint can be enabled so that bus state is
known. This is achieved by ORing XUD_STATUS_ENABLE into the relevant
endpoint in the endpoint type table.

This means that endpoints are notified of USB bus resets (and
bus-speed changes). The XUD access functions discussed previously
(XUD_GetData, XUD_SetData, etc.) return XUD_RES_RST if
a USB bus reset is detected.

This reset notification is important if an endpoint core is expecting
alternating INs and OUTs. For example, consider the case where an
endpoint is always expecting the sequence OUT, IN, OUT (such as a control
transfer). If an unplug/reset event was received after the first OUT,
the host would return to sending the initial OUT after a replug, while
the endpoint would hang on the IN. The endpoint needs to know of the bus
reset in order to reset its state machine.

Endpoint 0 therefore requires this functionality since it deals with
bi-directional control transfers.

This is also important for high-speed devices, since it is not
guaranteed that the host will detect the device as a high-speed device.
The device therefore needs to know what bus-speed it is currently running at.

After a reset notification has been received, the endpoint must call the
XUD_ResetEndpoint() function. This will return the current bus
speed.

XUD_ResetEndpoint()

  • XUD_BusSpeed_t XUD_ResetEndpoint(XUD_ep
     one, XUD_ep
     &?two)

    This function will complete a reset on an endpoint.

    Can take one or two XUD_ep as parameters (the second parameter can be set to null). The return value should be inspected to find the new bus-speed. In Endpoint 0 typically two endpoints are reset (IN and OUT). In other endpoints null can be passed as the second parameter.

    Parameters

    • one

      IN or OUT endpoint identifier to perform the reset on.

    • two

      Optional second IN or OUT endpoint structure to perform a reset on.

    Returns

    Either XUD_SPEED_HS – the host has accepted that this device can execute at high speed, or XUD_SPEED_FS – the device is runnig at full speed.

SOF Channel

An application can pass a channel-end to the c_sof parameter of
XUD_Manager(). This will cause a word of data to be output every time
the device receives a SOF from the host. This can be used for timing
information for audio devices etc. If this functionality is not required
null should be passed as the parameter. Please note, if a channel-end
is passed into XUD_Manager() there must be a responsive task ready to
receive SOF notifications otherwise the XUD_Manager() task will be
blocked attempting to send these messages.

USB Test Modes

XUD supports the required test modes for USB Compliance testing.

XUD accepts commands from the endpoint 0 channels (in or out) to signal which test mode
to enter via the XUD_SetTestMode() function. The commands are based on the definitions
of the Test Mode Selector Codes in the USB 2.0 Specification Table 11-24. The supported test modes are
summarised in the table below.

Supported Test Mode Selector Codes

Value

Test Mode Description

1

Test_J

2

Test_K

3

Test_SE0_NAK

4

Test_Packet

The passing other codes endpoints other than 0 to XUD_SetTestMode() could result in undefined
behaviour.

As per the USB 2.0 Specification a power cycle or reboot is required to exit the test mode.

XUD_SetTestMode()

  • void XUD_SetTestMode(XUD_ep
     ep, unsigned testMode)

    Enable a specific USB test mode in XUD.

    Must be run on same tile as XUD core

    Parameters

    • ep

      XUD_ep type (must be endpoint 0 in or out)

    • testMode

      The desired test-mode

Advanced usage is termed to mean the implementation of multiple endpoints in a single core as well as the addition of real-time processing to an endpoint core.

The functions documented in Basic Usage such as XUD_SetBuffer() and XUD_GetBuffer() block until data has either been successfully sent or received to or from the host. For this reason it is not generally possible to handle multiple endpoints in a single core efficiently (or at all, depending on the protocols involved).

The XUD library therefore provides functions to allow the separation of requesting to send/receive a packet and the notification of a successful transfer. This is based on the XC select statement language feature.

General operation is as follows:

  • An XUD_SetReady_ function is called to mark an endpoint as ready to send or receive data
  • An select statement is used, along with a select handler to wait for, and capture, send/receive notifications from the XUD_Manager core.

The available XUD_SetReady_ functions are listed below.

XUD_SetReady_Out()

  • int XUD_SetReady_Out(XUD_ep
     ep, unsigned char buffer[])

    Marks an OUT endpoint as ready to receive data.

    Parameters

    • ep

      The OUT endpoint identifier (created by XUD_InitEp).

    • buffer

      The buffer in which to store data received from the host. The buffer is assumed to be word aligned.

    Returns

    XUD_RES_OKAY on success, for errors see Status Reporting.

XUD_SetReady_In()

  • XUD_Result_t XUD_SetReady_In(XUD_ep
     ep, unsigned char buffer[], int len)

    Marks an IN endpoint as ready to transmit data.

    Parameters

    • ep

      The IN endpoint identifier (created by XUD_InitEp).

    • buffer

      The buffer to transmit to the host. The buffer is assumed be word aligned.

    • len

      The length of the data to transmit.

    Returns

    XUD_RES_OKAY on success, for errors see Status Reporting.

The following functions are also provided to ease integration with more complex buffering schemes than a single packet buffer. A example might be a circular-buffer for an audio stream.

XUD_SetReady_OutPtr()

  • int XUD_SetReady_OutPtr(XUD_ep
     ep, unsigned addr)

    Marks an OUT endpoint as ready to receive data.

    Parameters

    • ep

      The OUT endpoint identifier (created by XUD_InitEp).

    • addr

      The address of the buffer in which to store data received from the host. The buffer is assumed to be word aligned.

    Returns

    XUD_RES_OKAY on success, for errors see Status Reporting.

XUD_SetReady_InPtr()

  • XUD_Result_t XUD_SetReady_InPtr(XUD_ep
     ep, unsigned addr, int len)

    Marks an IN endpoint as ready to transmit data.

    Parameters

    • ep

      The IN endpoint identifier (created by XUD_InitEp).

    • addr

      The address of the buffer to transmit to the host. The buffer is assumed be word aligned.

    • len

      The length of the data to transmit.

    Returns

    XUD_RES_OKAY on success, for errors see Status Reporting.

Once an endpoint has been marked ready to send/receive by calling one of the above XUD_SetReady_ functions, an XC select statement can be used to handle notifications of a packet being sent/received from XUD_Manager(). These notifications are communicated via channels.

For convenience, select handler functions are provided to handle events in the select statement. These are documented below.

XUD_GetData_Select()

  • void XUD_GetData_Select(chanend c, XUD_ep
     ep, unsigned &length, XUD_Result_t &result)

    Select handler function for receiving OUT endpoint data in a select.

    Parameters

    • c

      The chanend related to the endpoint

    • ep

      The OUT endpoint identifier (created by XUD_InitEp).

    • length

      Passed by reference. The number of bytes written to the buffer,

    • result

      XUD_Result_t passed by reference. XUD_RES_OKAY on success, for errors see Status Reporting.

XUD_SetData_Select()

  • void XUD_SetData_Select(chanend c, XUD_ep
     ep, XUD_Result_t &result)

    Select handler function for transmitting IN endpoint data in a select.

    Parameters

    • c

      The chanend related to the endpoint

    • ep

      The IN endpoint identifier (created by XUD_InitEp).

    • result

      Passed by reference. XUD_RES_OKAY on success, for errors see Status Reporting.

Example

A simple example of the functionality described in this section is shown below:


void ExampleEndpoint(chanend c_ep_out, chanend c_ep_in)
{
    unsigned char rxBuffer[1024];
    unsigned char txBuffer[] = {0, 1, 2, 3, 4};
    int length, returnVal;


    XUD_ep ep_out = XUD_InitEp(c_ep_out);
    XUD_ep ep_in = XUD_InitEp(c_ep_in);

    /* Mark OUT endpoint as ready to receive */
    XUD_SetReady_Out(ep_out, rxBuffer);
    XUD_SetReady_In(ep_in, txBuffer, 5);

    while(1)
    {
        select
        {
            case XUD_GetData_Select(c_ep_out, ep_out, length):

                /* Packet from host recieved */

                for(int i = 0; i< length; i++)
                {
                    /* Process packet... */
                }

                /* Mark EP as ready again */
                XUD_SetReady_Out(ep_out, rxBuffer);
                break;
                
            case XUD_SetData_Select(c_ep_in, ep_in, returnVal):

                /* Packet successfully sent to host */
        
                /* Create new buffer */
                for(int i = 0; i < 5; i++)
                {
                    txBuffer[i]++;
                }

                /* Mark EP as ready again */
                XUD_SetReady_In(ep_in, txBuffer, 5);
                break;

        }
    }
}
//:

The following documents provide further reading regarding programming USB devices on XMOS platforms:

  • XMOS USB Device Design Guide
  • HID Class USB Device Quick Start Guide
  • USB Custom Bulk Device Quick Start Guide

Version history for this document.

Date

Version

Comment

2014-05-16

2.1

Updates to related to enabling test modes

2014-03-18

2.0

Added XUD_Result_t to API documentation
Added Further Reading section

2014-01-29

1.2

Minor updates. Added Advanced Usage and PwrConfig sections

2013-04-23

1.1

API updates and changes to Standard Request handling

2011-01-06

1.0

Updates for API changes

2010-07-22

1.0b

Beta Release

XMOS USB Device (XUD) Library Read More »

Scroll to Top