views:

145

answers:

3

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

+1  A: 

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).

Amoss
@Amoss Edited question to add code and assembler
dwelch
there is port setup that has to be done to make that work
dwelch
the setc's are related
dwelch
If you look at the simulation, this is where the output lines start to change<pre>0x0001024e: 00 f0 05 58: ldw (lru6) r0, dp[0x5]0x00010252: 08 e8: setc (ru6) res[r0], 0x8</pre>
dwelch
Are you running a different version through the simulator? That instruction doesn't occur at that address in the disassembly above.
Amoss
I did compile with -O2, there was still some fluff in the file but that probably moved the code around relative to the listing you are looking at
dwelch
0x10258 globcode is where it is in the listing above
dwelch
thanks for looking at this question and inspiring me to work on it again.
dwelch
Glad to hear it. Hope you have a lot of fun with the board.
Amoss
+1  A: 

Hi,

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...

Henk
@Henk thanks for helping out that sorta worked but didnt quite, see edit6 above.
dwelch
+1  A: 

Hi,

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.

Henk
the 0x8 and 0xf I understood from the docs the 0x6 I did not. are these clock blocks and the bits with this 6 in it in the XS1_en doc? is y a single bit so only two clock blocks?
dwelch
The least significant byte of a resource id signifies its type: 0x00 is port, 0x06 is a clock block (a full list of those is on page 105 of http://www.xmos.com//system/files/xs1_en.pdf); the second least significant byte enumerates each resource. Eg, channel ends count from 0x00 to 0x1f, clock blocks form 0x00 to 0x05, ports from 0x00 to 0x1f. The two most significant bytes are resource dependent; the width of a port, or the node/core id of a channel.
Henk
Cannot seem to edit the previous comment... It is meant to start "The number 0x6 is a resource identifier. In the same way that 0x40200 refers to port 4B, 0x6 refers to clock block 0."
Henk
ahhh, the lightbulb is glowing. page 105, I see now both where the 0x6 comes from and why there wasnt a getr
dwelch