Asking for simple improvement of the USI

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

For the first time I used the USI as half duplex UART
(see also application note AVR307). Well, it works just
fine. But I think some simple improvements would make the USI even more universal.

1. New feature: Inverse operation direction of the USI
When SPI mode enabled, the MSB is directly connected to
the DO pin and the bits are left shifted out of the
data register. So the MSB is transmitted first. When
receiving data the first incoming bit will end as the
MSB in the buffer register and the last incoming bit
will be located in the LSB of the buffer register.
But for UART transmission the LSB must be send first.
So the bitorder must be reversed whenever sending or
receiving data.
With the new feature enabled the DO pin would be connected
to the LSB in the data register, incoming bits are
stored to the MSB of the data register and the shift
direction is right. So no bit reversing is needed.
I guess this improvement is simple and would cost
only a few silicon.

2. New feature: Enlarge the USI from 8 bits to 12 bits
A standard UART frame takes 10 bits (1 Start, 8 data, 1 stop)
The USI can only handle max. 8 bits. So the data
register must be rewritten during sending an UART
frame. This is very time critical. For exampel: With
a clock of F_CPU = 1 MHz and a UART baudrate of 9600
baud, there are only 104 clock cycles left to update
the data register.
With a 12 bit USI it would be even possible to
implement the USART multi master communication mode
with a low CPU load.

What do you think about my suggestions?
Do you think they're usefull and an enrichment for
the ATtiny family?

Truly, if some of you professional industry developers
aggree to my suggestion, big brother Atmel won't
ignore us. Maybe you have even more reliable ideas.

Regards
Sebastian

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

I'm still interested in your opinion.

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

My guess would be that because of die-shrinkage future Tiny's may well have full UARTs on the silicon which would be a cleaner solution all round ;)

BTW were you not tempted by one of the small megas (48(P) perhaps) for the application where this Tiny was used?

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

Well it seems that some of the newer Tiny's are really baby mega's anyway.

An enhanced USI would be useful, as Sebastian suggests, as would dual USI's even in an eight pin package.

Dean

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

clawson wrote:
My guess would be that because of die-shrinkage future Tiny's may well have full UARTs on the silicon which would be a cleaner solution all round ;)

BTW were you not tempted by one of the small megas (48(P) perhaps) for the application where this Tiny was used?

The tiny24/44/48 have a nice feature which no other AVR has: The differential inputs can operate in bidirectional and unidirectional mode. So the ADC result is +/- 10 bit. In my actual project I need this feature.

Edit: A full USART would be much better than an enhanced USI, anyway.

Regards
Sebastian

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

I agree ..I wish they would make a full usart std on all devices even the 8 pin parts...in the meantime the Zilog Encore Xp 8 pin part may be a solution to your needs!

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

And if Atmel goes for an upgrade of the USI: the USI-counter can be used to extend the 8 bit Timer0 with 4 bits, creating a 12 bit counter.

One snag though: the overflow of Timer0 (from $FF to $00) should increment the USI-counter. It does, but one clock-cycle late :shock: . I.e. The USI-counter increments when Timer0 goes from $01 to $02. Gives strange results, once every 256 occurrances ...

Nard

PS I reported this twice to Atmel.

A GIF is worth a thousend words   They are called Rosa, Sylvia, Tricia, and Ulyana. You can find them https://www.linuxmint.com/

Dragon broken ? http://aplomb.nl/TechStuff/Dragon/Dragon.html for how-to-fix tips

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

I have been emulating a UART in Tiny AVRs by having the timer constantly overflowing at the baud rate. This works well for transmission. But it always misses about 1 out of 30 characters when receiving, even when using a crystal. The failure rate is about 1 of 15 using the internal timer, even with precision adjustment of the OSCCAL and the code algorythm. I believe that the USI would have the same problems doing UART-style input because it also uses one clock count per bit. The real UART uses 16 clock pulses per baud.

I recommend that Atmel put a real UART into the Tiny AVRs and drop the USI if there is only die space for one function. Nearly everything that the USI does can be done with code with little additional overhead. The sample code for the USI in the datasheets is not much different from its bit-banging equivalent.

I may be thick, but I find the USI to be endlessly confusing. I have to reread its entire datasheet section slowly and in depth every time that I use it.

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

Simonetta wrote

Quote:
I may be thick, but I find the USI to be endlessly confusing. I have to reread its entire datasheet section slowly and in depth every time that I use it.
I think 1. you're not thick and 2. same here .... re-reading etc etc . And I know of fellow freaks (smart ones ;) ) that dis-like USI too.

So dear Atmel: we have a proposal ... :)

Nard

A GIF is worth a thousend words   They are called Rosa, Sylvia, Tricia, and Ulyana. You can find them https://www.linuxmint.com/

Dragon broken ? http://aplomb.nl/TechStuff/Dragon/Dragon.html for how-to-fix tips

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

Quote:
I believe that the USI would have the same problems doing UART-style input because it also uses one clock count per bit

My ATtiny24 uses the USI as UART for Tx and Rx. I calcualted and tested a lot to set the sample point into the middle of
the incoming bits. Now the receiving of UART frames works very good after calibrating the internal oscillator. Even when waking up from Idle or power down mode. The USI saves a lot of CPU power comparing to a complete software UART.
The enviroment wasn't very noisy, of course.

BTW. The ATtiny24/44/84 USI can be clocked by a compare match of Timer0. So I had luck and no strange timing problems occured.

Regards
Sebastian

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

Hello,
Thank you for the reply and reporting your success using USI as a UART. Now that I know that it can be done, I will put more effort into getting it to work.

Could you share some working code? Do you code in C or assembler? Do you use a longer period for the initial period of a byte receive after the beginning of the start bit? Or three measured periods for the interval after the start bit and two periods for the other bits? Do you accept the received byte as complete in the period of the bit 8 or during the stop bit? Is your code able to receive several hundred bytes with no gap between the stop bit of one and the start bit of the next byte?
I've experimented with four or five different approaches to softUART input but all have failed to work 100 percent of the time. My best results have been one missed byte after thirty good ones.
I wonder if I should use a two-channel digital capture oscilloscope to help determine what is failing. The AVR code would put a single pulse on an I/O port pin when it reads the incoming data. One channel of the scope would capture the UART-incoming-data byte (trigger on the falling edge of the start bit) and the other channel would capture the pulses on the AVR I/O pin.
I don't have a digital capture scope but I believe that a PC sound card oscilloscope program could be used for this application. Most audio ICs on newer PC motherboards can sample at 96,000 times a second. This should work if the AVR I/O pulse is made long enough to be seen at this low sample rate.
I had considered migrating to the Tiny2313, but I like having the ADC available and the small pin-out size of the Tiny24. Maybe Atmel can make a Tiny29 with 8 or 14 pins, a full UART (does anyone use the syncronous section of the USART?), SPI, ADC, and 1K of internal SRAM and still sell for less than $1.50 US in quantity 25.

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

Quote:

I may be thick, but I find the USI to be endlessly confusing. I have to reread its entire datasheet section slowly and in depth every time that I use it.

I concur wholeheartedly. Trying to work out just how to clock out SPI data for ButtLoad required a LOT of re-reading, experimentation and swearing.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

Quote:

I concur wholeheartedly.

I agree that the USI leaves something to be desired...
Quote:

Trying to work out just how to clock out SPI data for ButtLoad required a LOT of re-reading, experimentation and swearing.

... but now you lost me. What does SPI on a Mega169 have to do with USI?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Quote:

... but now you lost me. What does SPI on a Mega169 have to do with USI?

Not senile, I swear!

In the ButtLoad firmware, the USI port is used to transmit and receive SPI data to and from the AVR device to be programmed. That limits the maximum programming speed to a little under 2MHz, but is necessary as there is not /SS select pin on the target AVR when programming, and the real SPI interface needs to run at a different speed to drive the on-board Dataflash.

Working out how to set up the USI as a SPI master took a lot of datasheet (re-)reading, and in the end I just took the Atmel examples as a given and just wrote my ASM driver using the same register fiddling.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

Simonetta,

Here's my USI as UART Code.
My target device is battery powered, so I send the tiny24 to sleep mode whenever possible. The tiny24 is clocked by the internal oscillator (calibrated to 1.0176 +/-1.1% MHz) because this clock provides the fastest wake up time (6 CK).

A 32Hz reference time signal comes from a tiny25 which is clocked by a 32768 Hz crystal divided by 8. In Idle mode the tiny25 consumes less than 20µA.

This reference signal is connected to pin PA7 (Timer1 input capture pin) and to PB1 (pin change interrupt PCINT9). So to test my code you have to connect an accurate 32Hz signal to these pins of your tiny24.

The time critical part is detecting the start bit of an incoming UART frame. Thus I had to write all ISRs in assembler, I use nested interrupts for the non start bit detection ISRs.

Pin PA5 is the Tx output and PA6 is the Rx input of the UART.

The USI uses Timer0 in CTC mode as clock source. I have enabled toggle pin OC0A (PB2) on compare match. If you connect the output signal of OC0A and the UART Rx signal to a scope or logic analyzer, then you can monitor when a bit is sampled.

The UART settings are: 9600 Baud, 8 data bits, no parity, 1 stop bit.

IDE is WinAVR.

I have not finished writing commentaries in the source code, yet. But almost. Feel free to ask, if there is something unclear.

Regards
Sebastian

EDIT: Ah, I forgot to mention how you can test the code. The program simply sends back the string is has received. The String can be up to 20 characters long and must be terminated by the cariage return (0x0D) character.

EDIT 2: The application note "AVR307: Half Duplex UART Using the USI Module" was a good start point for writing this program.

Attachment(s): 

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

Quote:

Quote:

I may be thick, but I find the USI to be endlessly confusing. I have to reread its entire datasheet section slowly and in depth every time that I use it.

I concur wholeheartedly. Trying to work out just how to clock out SPI data for ButtLoad required a LOT of re-reading, experimentation and swearing.

I agree that USI is very complicated...i'm trying to communicate two atmega3290 with the USI as SPI and even when i can see the clk, DO and DI signals perfectly with an oscyloscope i read the results "moved...out of phase..." (sorry i forgot the word in english).
i've read the datasheet many times, checked my code, the clk, and i still can't find the problem

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

Quote:
BTW were you not tempted by one of the small megas (48(P) perhaps) for the application where this Tiny was used?
I certainly would if they came in 8 and 14 pin packages (and may I suggest 16pin packages as well).

Ad suggestion 1)
I think that would break too much existing code. But making it configurable would probably work (and not use up much silicon).

Ad suggestion 2)
I'm in favour of that, also for all dedicated SPI modules in megas. Lots of LCDs have a 9bit SPI interface.

I feel that the hardest part about USI is its documentation. Atmel seems to try very hard to make a simple implementation look impressive (using obfuscation). Even with the given code examples are unnecessarily complicated.

Have fun,
Markus

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

Speaking of obfuscation: Could somebody enlighten me about USIBR ? (tinyX4)

It's there, it has an address, and when I read it the USIOIF flag gets cleared.

Markus

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

Could you post your code?
How did you discover this behaviour?
The simulator behaviour might differ from a real device.

Regards
Sebastian

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

I haven't used the USIBR register (since I don't know what it's for). But that is what the datasheet says (tinyX4, p.131, 16.5.3 USISR - USI Status Register):

Quote:
· Bit 6 ­ USIOIF: Counter Overflow Interrupt Flag
This flag is set (one) when the 4-bit counter overflows (i.e., at the transition from 15 to 0). An
interrupt will be generated when the flag is set while the USIOIE bit in USICR and the Global
Interrupt Enable Flag are set. The flag is cleared if a one is written to the USIOIF bit or by read-
ing the USIBR register. Clearing this bit will release the counter overflow hold of SCL in Two-
wire mode.

Markus

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

I guess Atmel meant that the USIOIE bit will be cleared when reading the USIDR. Maybe just an other error in the datasheet. I already posted some to Atmel. Now it's your turn!

In the code I posted above I always clear the USIOIE bit by software in the ISR because the interrupt is not only triggered after receiving data, it's trigerred when sending data is complete, too.

Regards
Sebastian

EDIT: The USIBR is for setting the USI baudrate. There are no information in the datasheet about this register. I already informed Atmel but got no response until now :(.

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

Setting the baud rate? A register call Data Buffer is for setting the baud rate? In a module that has to be clocked explicitly as master and is driven by input lines as slave ... interesting.

I sent Atmel an email, I'll keep you posted.

Cheers,
Markus

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

I got a response from Atmel today which clarifies the USIOIF behaviour:

Quote:
We agree that the information in the datasheet is not good enough, and we will update it.

We checked the design, and it work as follows for the Tiny24/44/84:

The USIOF bit should clear when reading the USIBR. However, if this happens at the same time that the shift register gets full the bit is not cleared.

Unfortunately no deeper insight on the USIBR itself yet. I'll keep you posted.

Have fun,
Markus

[edit]: spelling

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

Quote:
Until the datasheet has been updated:

Please see the description of the USIBR register in the Tiny25 datasheet. This description is also correct for the Tiny24.

Mystery solved. The USIBR seems to be a latched version of USIDR. Especially useful in slave mode, where new data can already be shifted into USIDR while USIBR is still available for reading.

Markus

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

Hi,

I've read many posts that say USIBR doesn't work or have the correct data in it when using the USI as an SPI slave and I found the same result last night. If I use the counter overflow interrupt and read USIDR, I get the correct value. If I use USIBR, I do not. Also, AVR's own AVR319 driver uses USIDR but NOT USIBR. Could it be that the USIBR is only really valid for 2 wire USI mode?

Thanks,

Alan