Has anyone been successful at a assembler based led blinker for an xcore?

2

I am liking the http://www.xmos.com chips but want to get a lower level understanding of what is going on. Basically assembler. I am trying to sort out something as simple as an led blinker, set the led, count to N clear the led, count to N, loop forever.

Sure I can disassemble a 10 line XC program, but if you have tried that you will see there is a lot of bloat in there that is in every program, what bits are to support the compiler output and what bits are actually setting up the gpio?

EDIT:

XC code

#include 
out port bled = PORT_BUTTONLED ;
int main () {
   bled <: 0b0011 ;
   while (1)
     ;
   return 0;
}

Commands to build

source SetEnv
xcc bob.xc -target=XC-1A -o bob.xe
xsim --max-cycles 2000 --vcd-tracing "-o bob.vcd -ports -cycles -threads -timers -instructions -functions" bob.xe

EDIT 5

Here is the answer

.globl _start
_start:
    ldc r0,4
    ldc r2,8
    ldc r3,16
    ldc r1, 100
notmain:
    sub r1,r1,1
    bt r1, notmain

    ldap r11,constants
    set  dp,r11

    ldc  r3, 0x6
    setc res[r3], 0x8
    setc res[r3], 0xf

    ldw r3,dp[0x0]
    setc res[r3],0x8
    ldc r1,0x6
    setclk res[r3],r1

top:

    ldc    r0, 0x8
    out    res[r3], r0
    bl delay

    ldc    r0, 0x4
    out    res[r3], r0
    bl delay

    ldc    r0, 0x2
    out    res[r3], r0
    bl delay

    ldc    r0, 0x1
    out    res[r3], r0
    bl delay

    ldc    r0, 0x2
    out    res[r3], r0
    bl delay

    ldc    r0, 0x4
    out    res[r3], r0
    bl delay

    bu top

constants:
.word 0x00040200

delay:
    ldc r2, 1000
da:
    ldc r1, 10000
db:
    sub r1,r1,1
    bt r1, db
    sub r2,r2,1
    bt r2, da
    retsp 0x0

building and loading the above assembler m.s:

xcc m.s -target=XC-1A -nostartfiles -o m.xe
xrun m.xe

you can sim and look at the pads/pins of the chip if you get rid of the delays so that you can see something happen in a reasonable length sim

xsim --max-cycles 2000 --vcd-tracing "-o m.vcd -ports -cycles -threads -timers -instructions -functions -pads" m.xe

but gtkwave doesnt like the syntax so to view that m.vcd file with gtkwave I have to edit the .vcd file and

from:
$var wire 1 paa10 0:X0D61 $end
to:
$var wire 1 paa10 X0D61 $end

Basically remove the 0: for all the paa variable definition lines.

With the above assembler x0d14, x0d15, x0d19, x0d20 are the pads that wiggle can see the connection from their documentation.

That magic number comes from an include file:

#define XS1_PORT_4C 0x40200

EDIT 6

Henk, thanks for jumping in to help. I was reviewing how far I had gotten and didnt understand the 0x6 and the setclk stuff and was going to have to re-ask a question or dig deeper. The code below does start to wiggle the port but then the xcore appears to do a thread swap and hang essentially, so it still isnt quite the simple program I was hoping for. And I understand this isnt a simple core (which is why I want to understand it at this level to make the most out of it).


.globl _start
_start:
    ldc r1, 100
notmain:
    sub r1,r1,1
    bt r1, notmain

    ldc r3,0x4020
    shl r3,r3,4
    setc res[r3],0x8
top:
    ldc    r0, 0x8
    out    res[r3], r0
    ldc    r0, 0x4
    out    res[r3], r0
    ldc    r0, 0x2
    out    res[r3], r0
    ldc    r0, 0x1
    out    res[r3], r0
    ldc    r0, 0x2
    out    res[r3], r0
    ldc    r0, 0x4
    out    res[r3], r0
    bu top

assembly
embedded
asked on Stack Overflow Jun 16, 2010 by old_timer • edited Aug 8, 2010 by old_timer

3 Answers

1

Post the assembly and I'll look through it for you. Sounds interesting.

Edit:

   0x000100ac: 00 f0 45 58: ldw (lru6)      r1, dp[0x5]
   0x000100b0: d2 a6:       mkmsk (rus)     r0, 0x2
   0x000100b2: c1 ae:       out (r2r)       res[r1], r0

I think this is the part that your looking for. I'll need to find an XMOS reference manual but based on the control-flow in main this must be the part that accesses the bled channel. To confirm it you could add a flag into the XC code and flip the LED in the while loop. This should add a similar access to the above into the assembly output.

According to the Instruction Set Reference (pg 123) the first operand for out is the port and the second is the data. The dp[0x5] operand looks like it is taking the handle for the port out of some kind of global bank and then using to look up the associated resource.

A man in the know suggested to me that you try -O2 to clean up the code. If you're trying to follow what is going on I would skip all of the initialisation code, it is always a mess on most platforms. If you just concentrate on the lines between the main label and the next procedure (DoException) then you should see a manageable amount of code that maps onto the part that you have written. The smaller btxx labels are jump targets for control constructs (while loops, if statements).

answered on Stack Overflow Aug 4, 2010 by Andrew • edited Aug 5, 2010 by Andrew
1

Assuming you program the machine raw, you need to get the port ID, which you can find in the xs1.h include file in the tools.

Load that port ID in a register, then use SETC to switch the port on, and use OUT to drive a value onto the port. Setting the clock of the port should not be necessary. Assuming you are using port 0x10000 the following sequence should give you a very short pulse. Use a timer to get a longer pulse; if you use a loop, the actual time depends on the clock speed of the processor and the number of threads. The timer gives you real time.

ldc r0, 1
shl r0, r0, 16 // Makes 0x10000
setc res[r0], 8
ldc r1, 1
out res[r0], r1
ldc r1, 0
out res[r0], r1

Hope this helps...

answered on Stack Overflow Aug 7, 2010 by Henk
1

Sorry, yes, you need to switch the reference clock block on and start it. So you need the three lines that I added to the program.

A resource of the form 0x00000y06 is clock block y, so 0x6 refers to clock block 0. setc 8 switches it on, setc 0xf sets the clock running. When the clock is "on" but not "running" (inbetween the setc 8 and setc 0xf) you can do things like change the divider setting. Uncomment the two lines to give the clock a divider, which will slow down the outs.

.globl _start
_start:
    ldc r1, 100
notmain:
    sub r1,r1,1
    bt r1, notmain

    ldc r3,0x4020
    shl r3,r3,4
    setc res[r3],0x8
    ldc r1,0x6
    setc res[r1],0x8
    // ldc  r2, 8
    // setd res[r1], r2
    setc res[r1],0xf

top:
    ldc    r0, 0x8
    out    res[r3], r0
    ldc    r0, 0x4
    out    res[r3], r0
    ldc    r0, 0x2
    out    res[r3], r0
    ldc    r0, 0x1
    out    res[r3], r0
    ldc    r0, 0x2
    out    res[r3], r0
    ldc    r0, 0x4
    out    res[r3], r0
    bu top

Hope this helps.

Henk

PS - a list of SETC values is in page 172 of the XS1 Architecture Manual.

answered on Stack Overflow Aug 9, 2010 by Henk

User contributions licensed under CC BY-SA 3.0