uEngine LED-hello-world

Tammo Spalink tspalink at CS.Princeton.EDU
Fri Jun 16 15:01:27 EDT 2000


I have managed to load the uEngines.  In case others are curious what
is necessary, I have included a program for the StrongArm which will
load a simple uEngine program to write the number "5" to the
evaluation board LEDs (similar to Scott Karlin's previous StrongARM
LED activation except for use of the uEngines).  It is intended to be
loaded with the VxWorks boot loader.

Getting this to work I have noticed a number of things in the manuals
that the Intel might want to look into.  I refer to the newest manuals
we have, dated "March, 2000".

(HRM sect 4.7) does not mention that the ECS bit should also be turned
off again.  Also the first step says the uEngine can be in the "Reset"
state.  This is not true: only the "Stopped" or "Paused" states work.

(HRM sect 4.6.3) does not mention that the VS bit in the
CTX_WAKEUP_EVENTS register for a given context must be set before that
context can be run by the arbiter.

(HRM sect 3.3, HRM sect 8.9.1, and PRM appendix C) disagree on the
bounds of the SRAM SlowPort memory region.

And finally some things that initially tripped us up:

(PRM sect 4) In the register description tables, the "Access" column
 sometimes incorrectly says "Read" even if a few bits of the register
are "Read/Write".  I suggest the Intel folks get rid of this column
entirely, since all of the information is provided by the "R/W" column
on the same page.

(Sort of HRM sect 4.7) The uEngines memory is word-addressed while the
StrongARM memory is byte-addressed.  It took me a while to notice this
means the uEngines do not have byte addressing bits at all.  That is,
I was using only addresses 0, 4, 8, and so forth.  The correct thing
to do wass use 0, 1, 2, 3, etc.  This difference also has implications
for comparing memory maps (for things like the LED addresses, etc).

Tammo

------------- uEngine LED activation code below --------------

typedef unsigned int uint32;

#define IXP1200_RESET 0x4200007C

static uint32 CSR_Base[6] = {
    0xB0000000,
    0xB0000800,
    0xB0001000,
    0xB0001800,
    0xB0002000,
    0xB0002800
};
typedef enum {
    USTORE_ADDRESS = 0x0,
    USTORE_DATA    = 0x4,
    ALU_OUTPUT     = 0x08,
    ACTIVE_CTX_STS = 0x10,
    CTX_ARB_CTL    = 0x24,
    CTX_ENABLES    = 0x28,
    CC_ENABLE      = 0x2C,
} csrOffsets;
static uint32 CTX_STS[4] = {
    0x34, 0x38, 0x3C, 0x40
};
static uint32 CTX_WAKEUP_EVENTS[4] = {
    0x54, 0x58, 0x5C, 0x60
};

inline extern uint32
memRead(uint32 address, uint32 bitOffset, uint32 bitCount) {
    uint32 mask = (0xFFFFFFFFul >> (32 - bitCount)) << bitOffset;
    uint32 value = *((volatile uint32 *)address);
    return (value & mask) >> bitOffset;
}
inline extern void
memWrite(uint32 address, uint32 value) {
    *((volatile uint32 *)address) = value;
}
inline extern uint32
memOverwrite(uint32 address, uint32 bitOffset, uint32 bitCount, uint32 value) {
    // Write value into a bitCount wide field bitOffset bits from the LSB
    // at memory location address, leaving the remaining bits as-is.
    uint32 mask = (0xFFFFFFFFul >> (32 - bitCount)) << bitOffset;
    uint32 prevValue = memRead(address, 0, 32);
    uint32 newValue = prevValue & ~mask;
    newValue |= (value << bitOffset) & mask;
    memWrite(address, newValue);
    return prevValue;
}
inline extern uint32
csrRead(int uEng, uint32 address, uint32 bitOffset, uint32 bitCount) {
    return memRead(address + CSR_Base[uEng], bitOffset, bitCount);
}
inline extern void
csrWrite(int uEng, uint32 address, uint32 value) {
    memWrite(address + CSR_Base[uEng], value);
}
inline extern uint32
csrOverwrite(int uEng, uint32 address, uint32 bitOffset, 
             uint32 bitCount, uint32 value) {
    return memOverwrite(address + CSR_Base[uEng], bitOffset, bitCount, value);
}

// The uCode.  Notice that 0x742000 is the memory-mapped address
// of the LEDs from uEngineLand.
uint32 ucode_Arr[] = {
  0xD8100008,            // immed_w0[ledaddr,  (0x742000        & 0xFFFF)]
  0xD8143A00,            // immed_w1[ledaddr, ((0x742000 >> 16) & 0xFFFF)]
  0xA00E0039,            // sram[write, $xfer0, ledaddr, 0, 1], ctx_swap
  0xDC000280,            // immed[$xfer0, 5] ;; in delay slot
  0xE00C0004             // ctx_arb [kill]
};
int ucode_Len = (sizeof(ucode_Arr) / 4);

void __main(void) {
    uint32 destAddr = 0x0;      // Where in the uStore to put code
    int uEng = 0;               // Which uEngine to use
    int ctx = 0;                // Which thread to use
    uint32 loadAddr;
    int i;

    // Take uEng out of reset state
    memOverwrite(IXP1200_RESET, uEng, 1, 0x0);
    
    // Load the uCode
    loadAddr = destAddr | 0x00000400;    // Set ECS bit
    for (i = 0; i < ucode_Len; i++, loadAddr++) {
        csrWrite(uEng, USTORE_ADDRESS, loadAddr);   // target uStore location
        csrWrite(uEng, USTORE_DATA, ucode_Arr[i]);  // desired uStore contents
    }
    csrWrite(uEng, USTORE_ADDRESS, 0x0); // Unset ECS bit

    // Prep the other uEngine state
    csrOverwrite(uEng, CTX_STS[ctx], 0, 10, destAddr);
    csrOverwrite(uEng, CTX_WAKEUP_EVENTS[ctx], 0, 10, 0x1);
    csrOverwrite(uEng, ACTIVE_CTX_STS, 0, 2, ctx);
    csrOverwrite(uEng, CTX_ARB_CTL, 2, 2, ctx + 1);

    // Start the thread
    csrOverwrite(uEng, CTX_ENABLES, 8 + ctx, 1, 0x1);

    // Wait for uEngine to finish
    while (csrRead(uEng, ACTIVE_CTX_STS, 2, 1)) {
        // Waiting...
    }
}

------------- uEngine LED activation compilation process --------------

arm-unknown-coff-gcc -nostartfiles -nodefaultlibs -fno-builtin  \
  -mcpu=strongarm110 -mapcs-32 -mno-sched-prolog -fvolatile -O2 \
  -Wall -Winline -Wstrict-prototypes -c demo.c
arm-unknown-coff-ld -X -N -e ___main -Ttext 00001000 demo.o -o bootimage.coff

---------------------------



More information about the ixp1200 mailing list