Enabling XTiny UPDI

Go To Last Post
9 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks to the chips Brian sent me, I have now analyzed the process of how to connect to the UPDI interface. This will eventually allow me to write my STK500v2 to UPDI interface, the objective is to turn a common arduino into a UPDI programmer.

 

But, to start at the beginning, I'm using as sources of information, the xtiny datasheets, of course, but also the pyupdi program done by Atmel people.

 

So, the first thing is to enable the UPDI peripheral. According to the datasheet, this should be done:

 

When the pull-up is detected, the debugger initiates the enable sequence by driving the line low for a minimum of 200ns and a maximum of 1us to ensure that the line is released from the debugger before the UPDI enable sequence is done.

The negative edge is detected by the UPDI, which requests the UPDI clock. The UPDI will continue to drive the line low until the clock is stable and ready for the UPDI to use. The duration of this will vary, depending on the status of the oscillator when the UPDI is enabled. A start-up time between 10us and 200us can be expected.

After this duration, the data line will be released by the UPDI, and pulled-high.

 

But when I looked at the pyupdi code, this initialization sequence was nowhere to be found, instead, a double-break sequence was seemingly used (see datasheet for details on what this is). I could be wrong, because my understanding of python is weak.

 

But anyway, I tested, and indeed the UPDI can be enabled in this alternative way, which greatly simplifies things, because this double-break sequence is also used to recover from errors. The datasheet says:

 

A double BREAK is guaranteed to reset the UPDI from any state.

So it seems, "any state" includes the disabled state, right after power on. And it's so much simpler than the "proper" enable sequence... This should be more clearly explained in the datasheet.

 

Ok, enough talk, I'll show some scope traces now. The yellow trace is the programmer side, blue is target (UPDI) side. Between them is a 4.7k resistor, and VCC is +5V for both.

 

First, a double break sequence:

 

 

This is just as recommended in the datasheet, a pulse of 24.6ms (that is 12 bits at lowest supported baud rate), followed by 1 stop bit, repeated twice.

 

Next trace is a close up on the first falling edge of the first double break sent immediately after powering up the XTiny, you can see that after less than 200ns (this time depends on input capacitance and resistor value), the UPDI reacts by setting the line as low output. Then, after less than 10us, it releases the line, so at the UPDI side, it drifts to a level set by the ratio of the 4.7k resistor and the UPDI pull up. At this moment, the UPDI is enabled.

 

 

 

Finally, on any subsequent double breaks, since the UPDI is already enabled, it doesn't respond by setting a low output state; instead it just stays as input:

 

 

 

Ok, that's it for now, next I will try to start talking to the UPDI.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, I managed to start talking to the UPDI interface. It was not as straightforward as I expected, because the interface has a curious behavior in output mode that is different from your typical UART, that I will comment about today.

 

As I mentioned, I want my project to run on a mega328p based Arduino. Since the 328P only has one hardware USART and it it is connected to the USB interface of the Arduino, I decided to write a software UART to talk to the UPDI.

 

I tested the software UART with a USB/serial adapter and everything was fine. However, when talking to the UPDI, the results were not very reproducible.

 

So I decided to take a look at the UPDI output with the scope, to see if anything was wrong.

The following trace shows the results. It is important to note that the software UART input was configured with pull-up enabled, I didn't think this would cause any problems. However...

 

 

The blue pulses are for debugging, they mark the moment of sampling.

From the yellow trace, it can be seen that the UPDI only goes output low for a brief moment at the beginning of each bit, then the line is kind of released and starts drifting up because of the pull up on the Arduino side. I say "kind of released", because it doesn't actually drifts to VCC, but to mid rail, as if there was a diode to ground on the UPDI side with somewhat over 2V drop.

 

Now this is not how UARTs usually operate, they keep a strong low for the whole bit, right? With the drift up, the Arduino side doesn't always read the correct input, especially if there is noise.

 

So I had to modify the input routine to disable the pull-up while sampling the data from UPDI. Now, the following trace was obtained:

 

 

Now, this problem is solved and I can talk to the UPDI, send commands and get results. For testing, I read the 16 UPDI internal registers from the Tiny1614 I'm using:

 

00100000 00000000 00000110 00000000 00000000 00000000 00000000 00000000 
00000000 00000011 00000001 10000010 00000000 00000000 00000000 00000000 

The 3rd register, Control A, doesn't have the default value of zero because I changed it in my test program to achieve faster transmission (default is 128 guard bits, I changed to 2 guard bits).

 

Now I think the low level issues are mostly gone, so I can start to write the actual STK500 to UPDI interface.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

yes

Looking forward to further UPDates and Information.

David (aka frog_jr)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've almost finished implementing the UPDI instruction set, so I was playing writing and reading stuff from the peripherals (not actually programming flash yet).

 

However, I found an undocumented feature while using the reset controller (one of the simplest peripherals of the XTiny). This peripheral has a register that holds flags indicating the causes of the resets, called the Reset Flag Register, RSTFR.

 

While reading this register, everything went as expected, the power on reset flag was set, of course, and after causing a reset via UPDI the corresponding flag is also set. All fine.

 

Then, I wanted to clear these flags. The documentation says that these flags are cleared by writing a "1" to them, so I just wrote 0xFF via the UPDI.

But to my surprise, all the flags where in fact set by this procedure. To clear them, I actually needed to write "0".

 

I also tested with interrupt flags, same thing.

 

My conclusion is that flags that are cleared when the CPU writes "1" to them, do not operate the same way when the UPDI is doing the writing. The UPDI can set and clear these flags at will, like normal bits.

 

I wonder if it's possible to trigger interrupts from the UPDI by writing the corresponding flags. If I remember I'll test this when I get to the stage when I'm actually able to upload a program.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I would say this was impossible, because normally the interrupt flags are not writable through any bus at all. It actually sounds like you're using the simulator, where we have allowed exactly this thing.

Which device?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

je_ruud wrote:

I would say this was impossible, because normally the interrupt flags are not writable through any bus at all. It actually sounds like you're using the simulator, where we have allowed exactly this thing.

Which device?

 

It's a real tiny 1614 and not a simulator. Don't tell me this feature is a bug and you want to disable it...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I wrote an example program, that dumps the entire contents of the target's address space via the UPDI interface. Then, it will send a 1Hz square wave via the target PB2 pin, that can be used to blink a LED (this wave is sent via the UPDI interface, it's not a program loaded on the target).

 

This program is meant to run on an Arduino class platform with a Mega 328P MCU. The interface with the UPDI target is digital pin 6 of the Arduino (via 4.7k resistor), and with the host system, the interface is the Arduino serial port @115200 baud, this is where the data will be sent, so it can be read/captured with a terminal program.

 

In case there is a problem, the Arduino will start blinking it's LED and instead of the address space, the internal UPDI registers will be dumped for diagnostic.

 

The zip file is an AS7 project and includes precompiled binaries and hex file.

 

If anyone wants to try this with UPDI compatible MCUs, I would be grateful for feedback. The MCU will not be written in any way, only reading will take place.

 

 

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

To get the UPDI response to behave better (and drive the whole bit), you should probably disable the collision detector with the first packet you send, as pyupdi does in the __init__:

 

self.stcs(constants.UPDI_CS_CTRLB, 1 << constants.UPDI_CTRLB_CCDETDIS_BIT)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

mraardvark wrote:

To get the UPDI response to behave better (and drive the whole bit), you should probably disable the collision detector with the first packet you send, as pyupdi does in the __init__:

 

self.stcs(constants.UPDI_CS_CTRLB, 1 << constants.UPDI_CTRLB_CCDETDIS_BIT)

 

You mean the behavior I described in post #2? Thanks, I imagined it would be related with collision detection, good to know it can be disabled if needed (I missed that bit in the datasheet :P).

 

Edit: BTW, could you reveal the meaning of bits 1 and 7 of ASI_SYS_STATUS, or is it some kind of secret? I'm asking, because they are set when my Tiny 1614 is operating normally, so they must signal some kind of "normal operation mode".

Last Edited: Sat. Dec 2, 2017 - 10:17 AM