Errata Sheet for XS1-G4A-FB512-C4 0835 ES N65285.00

Technical discussions around xCORE processors (e.g. xcore-200 & xcore.ai).
User avatar
Woody
XCore Addict
Posts: 165
Joined: Wed Feb 10, 2010 2:32 pm

Post by Woody »

I've had a quick look through your code and it looks good on the face of it. (You obviously have a better idea about our chip than I gave you credit for initially. Sorry for that.) I think Richard's replying at the moment, so I thought I'd just offer a suggestion for the UART rather than dealing with the problem you raise.

To avoid receiving data when a glitch causes a start edge which isn't valid for a full bit duration, you could test for a logic 0 half way through the start bit. Nice to see you're properly testing the stop bit and waiting correctly for the stop bit when it's not present.

As I say I'll leave it for Richard to respond to the actual problem you have!


richard
Respected Member
Posts: 318
Joined: Tue Dec 15, 2009 12:46 am

Post by richard »

va3ttn wrote:I remember the transputer having some special use for the memory location pointed to by Wptr,
and some other locations "at small negative offsets from Wptr".

With XS1, is it possible to induce an interference between timed input events
and TIMER events via some similar "special use" of memory locations?
The mechanism for events on the XCore doesn't use memory in any way. There are no special memory locations you must avoid.
User avatar
Woody
XCore Addict
Posts: 165
Joined: Wed Feb 10, 2010 2:32 pm

Post by Woody »

va3ttn wrote:Suddenly, UART receiver started to get blocked regularly, with quite predictable
average number of characters received before the blocking occurs.
The actual time it takes from startup to failure might be interesting too. Particularly if its around 20s or around 40s.
va3ttn
Member
Posts: 12
Joined: Sat Jul 03, 2010 1:46 pm

Post by va3ttn »

Could you clarify exactly what you mean by gets blocked?
Do you stop receiving characters or do you just miss some?
The blocking occurs exclusively when receiving characters.
With no characters arriving, everything would stay OK, even overnight.

When the "thing" happens, RXhandler waits indefinitely
for timed input event (sampling a data bit in the middle).

It is usually found waiting to sample the first data bit (RXstate = 1),
but is occasionally found waiting for the second or third one.

Once it misses, it hangs forever.

It can be brought back to life by TIMERhandler
detecting the blocked state and then setting RXstate to 10
(wait for high level) and configuring the input port to wait
for the high level on the pin. Receiver then runs just like
it's restarted, and blocks again after receiving some number of characters.
Do the TIMERhandler events continue to fire?
Yes.
I would suggest using xrun xgdb to read the register state of the thread and also read the data in the RXRecord after it becomes blocked to see if this reveals anything. The pc of the thread and the current RXState would be of particular interest.
I did so as described in comments just in front of the RXhandler.

PC stays entirely within TIMERhandler.
User avatar
segher
XCore Expert
Posts: 844
Joined: Sun Jul 11, 2010 1:31 am

Post by segher »

Maybe you shouldn't set the timer condition to AFTER? I reckon AFTER will set the
event active every cycle in your timer event handler, until the "setd", an as far as I
can see, the "setd" will not clear it.

The documentation doesn't really describe this stuff much. It would be great if
the "xs1 arch" doc had pseudocode for how the ports and timers etc. behave.
va3ttn
Member
Posts: 12
Joined: Sat Jul 03, 2010 1:46 pm

Post by va3ttn »

segher wrote:Maybe you shouldn't set the timer condition to AFTER?
Well, AFTER and NONE are the only options applicable to timers.

Timer seems to run correctly, as verified both in the simulator
and observing pulses generated by the timer handler.

Anyway, timer's due time gets advanced immediately after
timer event recognition, and before re-enabling events globally by WAITEU.
va3ttn
Member
Posts: 12
Joined: Sat Jul 03, 2010 1:46 pm

Post by va3ttn »

I've managed to reproduce the problem in 10.4 Simulator.

Proceed as follows.

1. Create an empty XC1 project, add the attached MAIN.S file and build.
The file is the same as above, plus an additional thread on the same core
to generate square waves with 11.52 kHz frequency. One period of the square
wave stands for one byte of 0xf0 at 115,200 bps (including start and stop bits).

2. Prepare a simulation as shown on Figures 1 and 2.
That is, run for 200,000 cycles, capture the trace,
connect pin XS1_PORT_1J to XS1_PORT_1I (core 0).

3. Run the simulation.

4. Open the ".vcd" file.
Select signals as shown on Figure 3.
Zoom Fit. Notice the cycle 141764 at 350.0 us.
Look at port 1I (UART RX input).
Its timeReg changes to 8912.

5. Zoom in around this point until something like Figure 4 appears.
The corresponding part of the trace file is also shown.

6. In cycle 141759 Timer0 increments to 8a6f, reaching the value set in line 1979 of the trace.
The timer event is recognized in cycle 141767 and TIMERhandler execution starts in cycle 141775.

7. In the meanwhile, the input port timer increments to 8911, reaching the value set in line 1959 of the trace.
THIS TIMED INPUT EVENT IS LOST FOREVER, as can be evidenced by scrolling the trace file and the waveform window.

8. RXhandler blocks indefinitely, and TIMERhandler continues to run.
Three bytes were received correctly, and RXhandler was blocked
waiting to sample the stop bit of the fourth byte (RXstate was set to 9 in line 1954 of the trace).

9. In the assembly file, line 71 "ldc r2, 800" can be changed to "ldc r2, 868",
and RXhandler will get blocked much faster, only 30,000 cycles need to be simulated.


I hope that some workaround is possible, so I won't have to scrap
my A4-sized four layer board hosting 2 XC-1 modules, Figure 5 :cry:
Fig 1.gif
Fig 2.gif
Fig 3.gif
You do not have the required permissions to view the files attached to this post.
Last edited by va3ttn on Fri Jul 23, 2010 11:34 am, edited 2 times in total.
va3ttn
Member
Posts: 12
Joined: Sat Jul 03, 2010 1:46 pm

Post by va3ttn »

Rest of the files.
Fig 4.gif
Fig 5.jpg

Code: Select all

   .text
   .file "main.S"
   .align 2

#include <xs1b_user.h>

   .globl main
   .globl main.nstackwords

   .linkset main.nstackwords, 0


// use of registers
//   r0..r3    arguments, return values   saved by caller
//   r4..r10   scratch                    saved by subroutine
//   r11       scratch                    saved by caller
//   cp        constant pointer           saved by subroutine
//   dp        data pointer               saved by subroutine
//   sp        stack pointer              saved by subroutine
//   lr        link register              saved by subroutine



//  RX record layout:
//       0  RXstate
//       1  portaddress
//       2  porttime
//       3  del10bit
//       4  del15bit
//       5  shiftreg
//       6  datareg
//       7  dataready

//  RXstate encoding:
//       0  wait for start bit
//    1..8  sample data bits
//       9  sample stop bit
//      10  wait for high level (initial state)



RXrecord:
  .int   10        //  RXstate = waithighlevel
  .int   0x10a00   //  portID  = 1I
  .int   0         //  porttime
  .int   868       //  del10bit (115200 bps)
  .int   1302      //  del15bit
  .int   0         //  shiftreg
  .int   0         //  datareg
  .int   0         //  dataready



port1J:
  .int   0x10800



//  UART TX thread

TX:
  ldap   r11, port1J
  ldw    r0, r11[0]         //  get port 1J ID to r0

  ldc    r1, XS1_SETC_INUSE_ON
  setc   res[r0], r1        //  turn the port on

  ldc    r1, 1
  out    res[r0], r1        //  pin initial value = 1

  ldc    r2, 800            //  with 800 run for 200,000 cycles;  with 868 run for 30,000 cycles

TXloop:
  setpt  res[r0], r2        //  set port time
  ldc    r1, 0
  out    res[r0], r1        //  future pin value = 0

  ldc    r3, 4340
  add    r2, r2, r3

  setpt  res[r0], r2        //  set port time
  ldc    r1, 1
  out    res[r0], r1        //  future pin value = 1

  ldc    r3, 4340
  add    r2, r2, r3

  bu     TXloop



// unsigned main (void);

main:


// int UART (void);

//  This non-returning function is called to initialize
//  and run indefinitely the UART RX and a timer.

UART:

  //  initialize TX thread

  getr   r0, XS1_RES_TYPE_THREAD
  ldap   r11, TX
  init   t[r0]:pc, r11
  start  t[r0]


  // initialize RXhandler

  ldap   r11, RXrecord
  or     r0, r11, r11       //  r0 points to RXrecord

  ldw    r2, r0[1]          //  get portID to r2

  ldc    r3, XS1_SETC_INUSE_ON
  setc   res[r2], r3        //  turn the port on

  clrpt  res[r2]            //  disable port timer

  ldc    r3, 1
  setd   res[r2], r3        //  set comparison value

  ldc    r3, XS1_SETC_COND_EQ
  setc   res[r2], r3        //  set port condition

  or     r11, r0, r0
  setev  res[r2], r11       //  set environment vector = pointer to RXrecord

  ldap   r11, RXhandler
  setv   res[r2], r11       //  set event vector

  eeu    res[r2]            //  enable events for this port



  // initialize TIMERhandler

  getr   r0, XS1_RES_TYPE_TIMER

  ldc    r1, XS1_SETC_COND_NONE
  setc   res[r0], r1        //  set timer condition to NONE

  in     r1, res[r0]        //  get current time
  ldc    r2, 434
  add    r1, r1, r2         //  compute due time
  setd   res[r0], r1        //  set due time

  ldc    r1, XS1_SETC_COND_AFTER
  setc   res[r0], r1        //  set timer condition to AFTER

  or     r11, r0, r0
  setev  res[r0], r11       //  set environment vector = timerID

  ldap   r11, TIMERhandler
  setv   res[r0], r11       //  set event vector

  eeu    res[r0]            //  enable events for this timer



  waiteu                    //  wait for event





//  "RXhandler" handles all the UART port events:
//    * detecting the initial high level,
//    * detecting the start bit,
//    * sampling 8 data bits and the stop bit.

//  See "RXstate encoding" at the beginning of the file.

//  RXhandler runs perfectly if TIMER events are NOT enabled.

//  It hangs on indefinitely if TIMER events ARE enabled,
//  apparently because a port timer event was missed
//  (and the subsequent one was NOT scheduled)
//  when it occured in the same thread cycle as the TIMER event.

//  This can be demonstrated by commenting in and out
//  the timer "eeu" instruction above.

//  The probability of a received character to block the RXhandler
//  is apparently equal to 1 / (TIMER period in REF cycles), i.e.
//  on average the RXhandler will run for "TIMER period" characters,
//  before getting stuck.

//  This suggests a possibility that a port timer event gets lost
//  when it occurs in the same thread cycle as the TIMER event.

//  RXhandler is usually stuck in the state "1", i.e. waiting
//  for the port timer event in the middle of the first data bit.
//  With decreasing probability, it was observed stuck in states "2" and "3",
//  waiting for the middle of the second and third data bits.
//  It was never observed stuck in states "0" or "10", i.e.
//  waiting for a specific level on the input pin.

//  Tested on XC1 board with a chip marked "XS1-G4A-FB512-C4  0835 ES  N65285.00"
//  I think this is the Rev. B of the architecture, and Rev. A of the silicon.

RXhandler:
  get    r11, ed            //  get environment vector = pointer to RXrecord

  ldw    r0, r11[1]         //  get portID
  getts  r1, res[r0]        //  get timestamp
  in     r2, res[r0]        //  get port data

  ldw    r3, r11[0]         //  get RXstate
  bf     r3, startbitfound

  eq     r4, r3, 9
  bt     r4, checkstopbit

  eq     r4, r3, 10
  bt     r4, waitstartbit   //  high level found



  // RXstate in [1..8], sample a data bit

  ldw    r4, r11[5]         //  get shiftreg
  shr    r4, r4, 1
  shl    r2, r2, 7
  or     r4, r4, r2         //  insert received bit
  stw    r4, r11[5]         //  save shiftreg

  // now prepare to sample the next bit (data bit or stop bit)

  add    r3, r3, 1
  stw    r3, r11[0]         //  advance RXstate

  ldw    r1, r11[2]         //  get porttime
  ldw    r4, r11[3]         //  get 1.0 bits delay
  add    r1, r1, r4
  stw    r1, r11[2]         //  save porttime
  setpt  res[r0], r1        //  set port time

  waiteu



startbitfound:
  add    r3, r3, 1
  stw    r3, r11[0]         //  advance RXstate

  ldc    r3, 0
  stw    r3, r11[5]         //  clear shiftreg

  ldc    r4, XS1_SETC_COND_NONE
  setc   res[r0], r4        //  set port condition

  ldw    r4, r11[4]         //  get 1.5 bits delay
  add    r1, r1, r4
  stw    r1, r11[2]         //  save porttime
  setpt  res[r0], r1        //  set port time

  waiteu



checkstopbit:
  eq     r4, r2, 1
  bf     r4, waithighlevel

  ldw    r4, r11[5]         //  get shiftreg
  stw    r4, r11[6]         //  save to datareg
  ldc    r4, 1
  stw    r4, r11[7]         //  set dataready

waitstartbit:
  ldc    r4, 0
  stw    r4, r11[0]         //  RXstate := wait for start bit

  clrpt  res[r0]            //  disable port timer

  ldc    r4, 0
  setd   res[r0], r4        //  set comparison value

  ldc    r4, XS1_SETC_COND_EQ
  setc   res[r0], r4        //  set port condition

  waiteu



waithighlevel:
  ldc    r4, 10
  stw    r4, r11[0]         //  RXstate := waithighlevel

  clrpt  res[r0]            //  disable port timer

  ldc    r4, 1
  setd   res[r0], r4        //  set comparison value

  ldc    r4, XS1_SETC_COND_EQ
  setc   res[r0], r4        //  set port condition

  waiteu





//  "TIMERhandler" just reschedules the timer and waits

TIMERhandler:
  get    r11, ed            //  get environment vector = timerID
  getd   r9, res[r11]       //  load previous due time
  ldc    r10, 433           //  TIMER period = 434 REF cycles
  add    r9, r9, r10
  setd   res[r11], r9       //  set new due time

  waiteu
You do not have the required permissions to view the files attached to this post.
User avatar
dave
Member++
Posts: 31
Joined: Thu Dec 10, 2009 10:11 pm

Post by dave »

Thank you for drawing attention to this and supplying such a clear description of the symptoms.
We have now been able to reproduce it on our simulators.

It appears to be a limitation of the port hardware. We will post some suggestions about how to avoid this problem
as soon as we have checked them.

We have checked that XC programs are not affected by this behavior - the instruction sequences compiled can not give rise to it.

Thank you for finding this issue and pointing it out to us. Can I offer you a reward - a free XC-1A or equivalent?
richard
Respected Member
Posts: 318
Joined: Tue Dec 15, 2009 12:46 am

Post by richard »

As Dave says you have encountered a limitation of the port hardware. The issue concerns waiting for events on a unbuffered port configured to become ready at a port time with no condition. If the port becomes ready at the same time as another resource and the event for the other resource is taken then the port will not generate another event until its configuration is changed.

For now I wanted to get back to you with possible other approaches that would allow you to progress with your project.

One possibility is to instead configure the port as a buffered port. You can configure a port to be buffered using:

Code: Select all

setc res[r2], XS1_SETC_BUF_BUFFERS
The effect of a timed input using a buffered port is slightly different to one using an unbuffered port. As with an unbuffered port, an unconditional timed input on a buffered port will become ready when the port time is met - at which point the the value on the pins is sampled. However, for a buffered port, at any subsequent tick of the port's clock new data will be sampled, overwriting the original value. Therefore if you set up an event for a buffered unconditional port but the thread is unable to take the event at the time it becomes ready (e.g. because it is busy handling other events) then the value read from the port after taking the event is the value input on the most recent clock tick and not the value when the time was first met.

For your application, it seems to me that this would work for the following reason. The maximum gap between the port time being met and the thread taking the event is bounded by the maximum time required to handle events on all the other resources in-between. The time required to service other events is likely to be small in comparison to one UART bit time as a UART is a relatively slow speed interface. Therefore the pin will be sampled very close to the middle of the each bit which should allow you to read the data correctly.
Last edited by richard on Sat Jul 24, 2010 12:40 am, edited 4 times in total.