AT90USB + assembly code?

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

I've been looking around for some practical code for the AT90USB range of controllers, but all I can find are written in C.
I've been reading through the very informative "USB in a NutShell" article over at http://www.beyondlogic.org/usbnu...
Need to read it a few more times before I got it all in my head, but I got the general idea already. What I'm missing is a way to apply the stuff I learned in that article to an AT90USB device. How much is already done in the hardware? What do I need to do in software, and in what order?
Because all I know (and intend to know) about "C" is that it's a programming language, I'm having a hard time understanding the app notes and the MyUSB code.

What I'd love to have is a small assembly code sample that would make the device show up as a HID keyboard when connected to a PC. Anything beyond this, I think would just add to the confusion. That's why I'm not (yet) trying to disassemble pre-built hex files from IE MyUSB or other sources.

Feel free to yell at me for not learning C. You're not the first, and likely not the last.

So if any of you who already got the "hang" of this could try to give me some hints and clues to what needs doing to make the AT90USB into a HID Keyboard (or any other basic device), I'd be a happy camper. If I actually make it work, I'll try to make my findings available to ohers (all 4 of them) who prefer ASM over C .

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

Get ready for a lot of reading! USB in itself is a major topic and not trivial to implement. If you've had a look a the 'c' code, you'll see that there's a bit of code - so to write this in assembler is a labourious task. You'll also want to be an accomplished assembler programmer. Personally, I'd be writing it in 'c' and I've done a lot of assembler! The language 'c' embodies some basic computer science concepts - learn these and you'll be able to write better assembler code - I've had to work on some nasty assembler code projects over the years.

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

Kartman wrote:
Get ready for a lot of reading! USB in itself is a major topic and not trivial to implement. If you've had a look a the 'c' code, you'll see that there's a bit of code - so to write this in assembler is a laborious task. You'll also want to be an accomplished assembler programmer. Personally, I'd be writing it in 'c' and I've done a lot of assembler! The language 'c' embodies some basic computer science concepts - learn these and you'll be able to write better assembler code - I've had to work on some nasty assembler code projects over the years.

Well Kartman, this is certainly a refreshing twist!

Of all of the assembler/C arguments I've heard over the years, I definitely appreciate your perspective on assembler verses C.

You can avoid reality, for a while.  But you can't avoid the consequences of reality! - C.W. Livingston

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

Well.. I've seen there's "a bit of code", but as I struggle to make heads or tails of this C stuff (.h files, .c files, makefiles, dependencies and all that lot), I'm left with the impression there's alot of "Define" this and "Define" that, but not really that much real code going on. It's just that I find the actual code bits almost inpenetrable due to all it's dependencies. Say

if($var2 == #const_usb_stuff){
    do_weird_macro($another_variable);
}

I'll need to look up all those variables, macros and constant to even start to understand what's going on.
But this is really beyond the point, as this tread was not intended to kick off yet another C vs ASM debate. What I'm basically looking for is a language-independent flowchart or "to do"-list to operate the USB functions inside the USB enabled AVRs. From what I've gathered, ATMEL has implemented much of the time-critical and bit-level stuff into the actual hardware, so all the developers need to do is to configure the hardware buffers related to the different endpoints, and from there, it's just the matter of reading from or writing to these buffers (and their related control registers) to generate the various descriptors and eventually do usefull stuff.

I'm that kind of guy that don't trust a "printf()" macro to do exactly what I want or expect at the exact time I want it done. The only time I do any cut 'n paste in code, is when I try to learn new stuff. Then I see what's going on and build my own code to do the same function as the stuff I borrowed, but on my own terms. That way I'm always in control of what's going on.
You might argue that this is a very cost in-eficcient and an overly elaborous approach, and you might be correct if the goal was commercial, where time-to-market is crucial. This is not the case. My primary motivation is to learn. I've learned alot about computers this way. Alot of stuff I wouldn't pick up if I just took someone elses code and just modified it to sort-of do what I wanted.

That's why I'm asking for someone who have some experience with these devices to give me a few hints on what this really is, and how it works, and possibly even what they did to figure this out themselves. I don't want to re-invent the weel because I'm stubborn or old-fashioned. I want to reinvent the weel because I like doing it.

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

I am happy with C, but struggle with following the USB code. I would be completely lost if the code was in assembler.

All the AT90USB devices are fairly large. You will have to a lot of typing to fill them up with assembly code.

What most people want is some simple library functions that handle the USB at a higher level.

Then you or I could call them via either C or assembly language. I do not care which language the library was written in. Just that the calling procedues and functionality are well documented.

David.

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

I took some time to re-read a few of the datasheets for the USB parts side-by-side with the article I mentioned earlier. I still haven't connected all the dots.

I'm considering getting a few of these AT90USB parts and a STK525. The reason I'm going for that, and not the USBKEY is I already got the STK500 (2 actually).

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

I'm the author of MyUSB. While I can't help you program the system in ASM (being a mediocre ASM programmer myself) I can at least help you understand what you need to do.

Basically, the USB hardware is a bit like a seperate microcontroller bolted to the core. This USB controller managed endpoint transfers, errors, data banks and the like, and communicates with the AVR core via a large set of registers.

For device mode, you need to:

1) Enable USB controller
3) Start 40MHz PLL via the PLL register
4) Wait until PLL gets a lock
5) Enable USB pad regulator if your supply voltage is outside the allowable range for the D+ and D- pads - see datasheet
6) Set device mode via UIMOD bit
7) Set low or high device speed mode via LSM bit
8) Enable USB interface via USBE bit
9) Unfreeze USB clock via FRZCLK bit
10) Configure control endpoint (endpoint 0, single-banked, 64 byte CONTROL type endpoint)
11) Attach the device via DETACH bit

From there you can then check for attach status (to a host) via the VBUS bit. To make a working device you then need to periodically check endpoint 0 for waiting control requests, which you must service according to chaper 9 of the USB 2.0 specification.

- Dean :twisted:

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

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

Quote:
there's alot of "Define" this and "Define" that, but not really that much real code going on
But the definitions would be the same in assembler, in fact I can use C header files in assembler, at least that is the case with assembler version 2.

Of course you can do without spending time defining things, but then your life would become pretty hard, either C or asm. :)

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

The Atmel code was written to work on a number of compilers and processors - so to read it can be hard work until you understand the how's and why's of what they're doing. It's actually a good lesson on how to write 'portable' code. Portable being for different compilers.

dukerX - printf isn't a macro! Its a function. As to why you would worry about it is beyond me - you end up writing similar functions in assembler to do the exact same thing. Many compiler implementations of printf are written in assembler!

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

Quote:
1) Enable USB controller
3) Start 40MHz PLL via the PLL register
4) Wait until PLL gets a lock
5) Enable USB pad regulator if your supply voltage is outside the allowable range for the D+ and D- pads - see datasheet
6) Set device mode via UIMOD bit
7) Set low or high device speed mode via LSM bit
Cool Enable USB interface via USBE bit
9) Unfreeze USB clock via FRZCLK bit
10) Configure control endpoint (endpoint 0, single-banked, 64 byte CONTROL type endpoint)
11) Attach the device via DETACH bit
In a few years the new 'newbie' question will be 'I can't get my usb port to work' instead of 'I can't get my serial port to work'. Dean will spend all his spare time answering usb questions. Cliff will have faq#17 on his signature- '99% of all usb problems are because you don't know anything about usb'.

Me, I'm waiting for 'Serial Port 2.0'.

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

JS: It's an emotional thing. It's just that I don't like the structure used in C.
Kartman: Portable code is good, and I think ATMEL did the right thing making it so. My mix-up of macro/function just goes to show my lack of knowledge about C.
On the other hand, it seems counter-productive to have a "sample code" that requires you already know how it works.
curtvm / Dean: If/when I get this stuff to work, I'll write a hands-on article/tutorial describing how to get from the blank chip to a device that can be connected to a (windows) PC and identify itself as a HID mouse or other generic device.
Target "audience" would be ppl who have some experience with AVR, but little or no knowledge about USB.
I expect that when I get a basic HID device working, and more importantly know how/why it works, I should be able to build on that, and make more exotic stuff from there.

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

Well by all means take a look at my sample MyUSB demo projects - they cover a wide array of tasks (audio, HID, mass storage, CDC, etc) and are easy to follow even without a good knowledge of C, once you get the general hang of USB.

- Dean :twisted:

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

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

I should probably just dive in- get a USBkey and attempt to figure it out. (I would like to make my own serial-usb converter, and I like the price of a AT90USB82).

The only sticking point that I'm not sure of, is the VID/PID thing. If I made a device that I could sell (humor me), it seems I would have to sell a lot of them just to recover the cost of getting a VID. Maybe there are alternatives, or I'm misunderstanding the VID/PID thing (hence the hesitation to even spend a lot of time figuring the usb thing out). Don't Know.

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

Quote:
JS: It's an emotional thing. It's just that I don't like the structure used in C.
Hey, I know how you feel. You are talking to the #1 asm poster here: The asm champion :lol: nice to have some help though.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

Dean: Do you think that I figure out how to construct a program that makes the AT90USB operate as a HID keyboard or mouse, I should be able to make any other device based on what I already learned?

The reason I'm so obsessed with these HID devices is they appear fairly simple and they don't need me to write any drivers for them to operate on most common OS.
For instance; I've found out my Intellimouse Explorer 3.0 has just 2 endpoints. The default Endpoint0 for control, and one 4 byte IN endpoint. A wild guess here would be that those 4 bytes are much the same a the ones in a PS/2 mouse "motion" frame.

From what I've gathered regarding VID and PID, I got the impression you don't need to buy your own VID. You could actually talk to someone who already owns a VID and obtain a unique PID from them. Much the same as a subdomain on the internet (like maps.google.com where maps is the subdomain controlled by google, while the google.com is a top domain wich are controlled by ... NIX, or whatever they are called). For your own personal prototyping work (or even share-with-your-friends work), there shouldn't be any problems in "borrowing" someone elses VID... as long as you don't make a device that has the same VID and PID as another USB device you are already using.

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

DukerX, like most things to do with computers these days, USB is not trivial. You need to know a lot before you can do a little - even knowing the terminology and what each term means is a bit of work. When I got my USBKey, I spent a lot of time reading this book:
http://www.amazon.com/Universal-...

Which explains each process clearly. Once you understand the terms and the processes involved with USB, then the Atmel datasheet makes sense. The sample code also starts to make sense. I'm sure Dean will agree with me here in that you need to get about 5 things correct before anything will happen and when things go wrong, you have to use a USB sniffer program to try and figure what went wrong. This is not to deter you, but realise it is non trivial.

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

Quote:

I'm sure Dean will agree with me here...

I do agree, but I actually did it all without it. I managed with only a USBKEY, the datasheet (an updated version from the one on the site), a JTAG and a C compiler and a program called USBView to look at the returned descriptors. Granted, I also had Atmel's code to look at when things got *really* bad, but mostly I got it going out of perseverance.

However, the point of my labor was to make things easier for others, by providing a nice library for others to use. What you're doing is re-inventing the wheel. You could use the GNU-GAS assembler in AVR-GCC, and write your user code in assembly and keep my library in C.

I started in little steps. First, read the USB sections of the datasheet. Try to get the controller to attach to the host and receive VBUS. Then try to create the control endpoint, then read chapter 9 of the USB specification to get it to enumerate.

It is a complex beast and if you lack patience I suggest reading one of those books Kartman suggests. Or just learn C instead (better!) and use my already pre-made wheel.

- Dean :twisted:

PS: And yes, a HID device is extremely simple once the controller and framework is written.

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

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

abcminiuser wrote:
I'm the author of MyUSB. While I can't help you program the system in ASM (being a mediocre ASM programmer myself) I can at least help you understand what you need to do.

Basically, the USB hardware is a bit like a seperate microcontroller bolted to the core. This USB controller managed endpoint transfers, errors, data banks and the like, and communicates with the AVR core via a large set of registers.

For device mode, you need to:

1) Enable USB controller
3) Start 40MHz PLL via the PLL register
4) Wait until PLL gets a lock
5) Enable USB pad regulator if your supply voltage is outside the allowable range for the D+ and D- pads - see datasheet
6) Set device mode via UIMOD bit
7) Set low or high device speed mode via LSM bit
8) Enable USB interface via USBE bit
9) Unfreeze USB clock via FRZCLK bit
10) Configure control endpoint (endpoint 0, single-banked, 64 byte CONTROL type endpoint)
11) Attach the device via DETACH bit
:twisted:

How important is the order in which the above steps are performed?

I'm currently working on some code, and am able to get a VBUS int, and am able to configure my control ep, but am having difficulty enumerating properly.

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

Reasonably important, but for the most part non-critical. What trouble are you having with the enumeration?

- Dean :twisted:

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

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

I've used Atmel's at90usb-demo-template as a starting point (rewrote it to eliminate all of the unnecessary code) for my HID device class interface, so I'm using Atmel's basic USB FW structure, if you're familiar with that. Within this structure, there is a function "usb_device_task" which looks for the USB Rx flag, then goes off and processes the received data if the flag is set. For some reason, this flag doesn't seem to be getting set, so I'm not able to process the host's request for descriptor info.

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

Are you using C, or assembly? If the former, download my MyUSB library and be done with it - it's tested working and includes several HID examples.

Not familiar with Atmel's library. It's structure was the reason I binned their code and wrote my own library in the first place.

Are you talking about control requests on endpoint 0, or the data endpoint?

- Dean :twisted:

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

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

Time to revisit this topic...

I am now in the posession of a JTAGIceMkII and an AT90USBKey.
I got the USB2.0 spec and have spent a few afternoons trying to understand it.

I have made a program that
-enables the PLL
-enables USB unit in fullspeed device mode
-upon VBUS detection, the ATTACH bit is cleared
-after getting a USB reset, I configure EP0 as Control, OUT, 64 byte, single bank Alloc=1 and then enable it.

I also enabled all the EP interrupts except TXINE.
Is this correct so far?

Because this USB stuff is impossible to debug using JTAG, I use breakpoints scarcely, and the only one I have atm is at the EP interrupt vector.

When the EP interrupt fires, I have received 2 USB reset events (counter in the USB reset interrupt routine). It appears the EP interrupt was triggered by a RXSTPI event.

I find it slightly odd I should receive 2 USB resets before getting the SETUP package.
I still haven't figured out how much of the USB stuff is handled by the hardware, so I'm not quite sure what to expect to get if I try to read out the EP0 FIFO.

What exactly should the content of the EP0 FIFO be after 2 resets and the 1st RXSTPI event?

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

Yes, the host usually sends a couple of resets to ensure the device is in the default power-on state, ready for enumeration. Why it sends multiple reset events is anyone's guess, but it doesn't hurt anything.

After the resets, the host will start issuing control requests on endpoint 0. These are the requests as detailed in chapter 9 of the USB 2.0 specification, and cover the requests to properly enumerate the device to the host -- Get Descriptor, Set Address, etc.

You will need to implement all the mandatory chapter 9 requests. You can take a look at my MyUSB library to see a working implementation of each request, but the actual transmission sequence follows the "control transfer" information in the USB specification.

Chapter 9 requests contain a Host->Device header of several bytes (Request, Request Type, wValue, wIndex, wLength) followed by an optional data stage (Device->Host or Host->Device) and finally a status stage to complete the request.

Once you've implemented the chapter 9 requests, the device will show up on the host an you can start creating USB devices by writing the appropriate USB descriptors and initializing the appropriate endpoints.

The USB hardware takes care of the actual packet transmission and reception. Once a packet (IN, OUT or SETUP depending on the endpoint) is received the bank is locked by the controller until you unlock it by clearing FIFOCON.

- Dean :twisted:

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

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

For both of you who have been following this thread, I'm posting a micro-update.

I have made some progress in my attempts of programming the AT90USB1287 using only Assembly, and I am now at a point where my USBKey is in the "Addressed" state, and I'm working on the code that sends the Configuration descriptor back to the host.

I'm not ready to claim I "got" the USB controller hardware yet, but I'm starting to understand what is being handled by hardware, and what needs handling by software.

In the next update, I hope I can report success, but we'll see..

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

I've been looking around for some practical code for the AT90USB range of controllers too. All examples that I seen with problems. Userial project cant find a driver. It tells that inf file for another device. MyUSB project demos work with another cristal rezonator. I dont undestand GCC. Haw I can change MCU type or frecuency, PLL in GCC? Many files, many defines that points one to another. Why people use high level programming language GCC fol low, hard level devices?
In assemly:
out PortC,x
- 1 command, 11 characters, easy to understand.
In GCC: enable_motor_driver_pullup_to_back_transistor_caca_on_device_number_3;
- ??? haw many commands, 1-2 lines, this defined in another file in wich many another defines. Optimization only by machine. Very bad results of using GCC as for me.

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

lol

Quote:

MyUSB project demos work with another cristal rezonator.

I'll wager that for proper USB operation, there are a limited set of clock speeds that can be used. Yep--the datasheet says
Quote:
6.1.4 USB Clock – clkUSB
The USB is provided with a dedicated clock domain. This clock is generated with an on-chip PLL running at 48MHz. The PLL always multiply its input frequency by 6. Thus the PLL clock register should be programmed by software to generate a 8MHz clock on the PLL input.

I'm just guessing that Dean never used a resonator.

If you want to use all magic numbers, and no named or computed constants, that is up to you.

Quote:

In assemly:
out PortC,x
- 1 command, 11 characters, easy to understand.

In C: "PORTC=x;". 8 characters. So it is already 27% better than your ASM solution. How you get x or what you call it, and how many letters in the name, are up to you. (Back to the minimalist BASICs and Cs, with only single-letter variable names allowed. It sure did make for compact parsers, tho.)

Lee

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:
In GCC: enable_motor_driver_pullup_to_back_transistor_caca_on_device_number_3;
In asm
rcall  enable_motor_driver_pullup_to_back_transistor_caca_on_device_number_3 
 

if that's what your routine is called. :)

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

DigitalMaster wrote:
I've been looking around for some practical code for the AT90USB range of controllers too. All examples that I seen with problems. Userial project cant find a driver. It tells that inf file for another device. MyUSB project demos work with another cristal rezonator. I dont undestand GCC. Haw I can change MCU type or frecuency, PLL in GCC? Many files, many defines that points one to another. Why people use high level programming language GCC fol low, hard level devices?
In assemly:
out PortC,x
- 1 command, 11 characters, easy to understand.
In GCC: enable_motor_driver_pullup_to_back_transistor_caca_on_device_number_3;
- ??? haw many commands, 1-2 lines, this defined in another file in wich many another defines. Optimization only by machine. Very bad results of using GCC as for me.

It's LUFA now (the Lightweight USB Framework for AVRs) rather than MyUSB. Same thing, different name.

LUFA is limited by the clock speeds that the AVR's USB controller will accept. It will automatically work when a clock speed suitable (as per the datasheet) is used with the device, with the corresponding clock speed given in the project makefile at compile time -- that's how the C code is aware of what clock speed you will be running your code at.

Both 16MHz and 8MHz will work with USB.

- Dean :twisted:

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

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

Now MyUSB projects works. I find clock end device in makefile. Im add my task to one of the project and I see that programm service my task in circle after many operations. In my project I need good speed with ports. I must create 1 main circle with port scanning and interrupts. But in MyUSB, I see, many routines and calls.

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

I like MyUSB pragramm architecture, it really easy to use. But I cant optimized it.
Yuu can use PORTC=x, but C# programmers always use XXX_XXX_xxx_xx;
out PORTC,x - only 6 characters; "out" - processor command that indicates 1 programm word and I know how meny CPU circles this command executed from datasheet. It is very impotant in process of optimization. Assembly programmers always can take twice perfomance from MCU. I have device in tiny2313, wich make videoprocessing in real time mode. It calculates traffic from analogue videocamera on 4 sections, generates characters (time, traffic) and add its to the output CVBS videostreem. Assembly!
Or look at this:

INTRoutine1:

sbic PORTB,0
rjmp Exit

reti

INTRoutine2:

Exit:

reti

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

Read DukerX 's comments and Dean's informed replies. I appreciate the argument for C but still love assembler and its absolute demand that I know what the processor is doing in order to get a program to work.

I'm trying to get a Host HID interface to work with the AT90USB1287 to work with a 1D barcode scanner. As I know what this scanner sends back (using a cheap  traffic monitor), I thought I could cut down the 'hello who are you chat' and get straight to 'send me your data'  following a pretty short setup.

I echo the plea for more transparency on what the processor actually does. For example the sequence of freezing/unfreezing buffers, their reading and the interrupt trigger sequence. I can hazard a guess for these, but it would be so nice if the documentation expanded on these topics.

Dean, you were kind enough to set out the steps for Device mode, please could you do this for the Host mode?

Thanks

John