My Not-so-Secret Project

Quick bit of related news: it seems the University of Queensland’s approved my LUFA library for student use!


This last week I’ve been working on a little LUFA side project, for inclusion into the next release. Actually, it’s something I previously thought impossible with the USB AVRs, but after (quite) a bit of experimentation it turns out the little USB AVRs are more useful than I previously thought.

Things all began while I was chatting on Freenode IRC in #avr, #bumbleb and #dorkbotpdx (fun fact, I’m usually there under the guise of abcminiuser, come and say hi!) last week and wondered if it was worth trying to make an AVRISP-MKII with the USB AVRs. Don Delmar “you’re only here because we like your library” Davis was rather taken by this idea – after all, it would mean “real” $20 ISP programmers with infinite customisation and AVRStudio integration, and so at his encouragement I started work.

Now, to be fair, this isn’t a new idea — I was asked if the same thing was possible by another user whose name I can’t seem to dig up last year and I replied in the negative. Times have changed and my knowledge of what the chips can do has improved; since then I’ve discovered that the larger USB AVRs can support bidirectional endpoints while in host mode by freezing, changing the token and unfreezing a pipe. That made me wonder if the same was possible in device mode with the USB endpoints.

Turns out, yes, it’s possible, and there’s a new Endpoint macro to do just that in the latest SVN revisions. The trick is to set the endpoint as OUT until data is needed to be sent to the host – if so, change the direction, write your data, send it, wait for the IN bank to be ready again and switch back to the OUT direction. This means the communication is half-duplex, but it also means that for low-bandwidth applications one of the precious few endpoints can be saved for other uses. Since the largest USB AVRs have only a single bank capable of 256 byte packets, this means very fast half-duplex transfers in either direction.

This is monumental — it means that all sorts of neat applications can be made, starting with the AVRISP-MKII clone using the Atmel USB AVRs. And that’s what I’ve been doing – writing my own firmware from scratch. You can try it out in the latest SVN revisions under Projects/Incomplete/AVRISP, which is almost complete; everything except FLASH and EEPROM writing now works. I realise the latter is a rather big drawback for a programmer device, but I’m getting there and I’m happy with the week’s work. By next week, everything should be in place for a cheap knock-off of the official AVR-ISP using anything from a lowly AT90USB82 all the way up to a big AT90USB1287.

I’ve got big plans for this project once I’ve got the initial version (and all the other LUFA features that have been queuing up for the next release) complete – such as a one-touch mode to toggle between AVRISP programmer and CDC class USART/I2C/SPI debugger. Stay tuned.

 

Comments: 21

Leave a reply »

 
 
 

[…] for 2009-08-23 My Not-so-Secret Project (tags: […]

 

Hi Dean,

Are you testing against 64-bit Windows? I compiled the code, stuck it on a Teensy and plugged it in. It was correctly detected as a “LUFA AVRISP MkII Clone Programmer”, but failed to install the driver. The following error is in Device Manager:

This device is not configured correctly. (Code 1)
A service installation section in this INF is invalid.
To find a driver for this device, click Update Driver.

The Jungo driver that Atmel supplies is version 10.0.1.0. According to the release notes for AVR Studio 4.17 (which I’m running) one of the fixed issues is “6093 USB driver installation on Windows Vista x64. Upgraded to latest Jungo driver.” which implies that it should work correctly.

Regards,

Mike

 

Mike,

No – I haven’t got a 64-bit installation around to test it with. However, my device has nothing to do with the host side, which uses Atmel’s stock drivers. It sounds like you haven’t installaed the new drivers during the 4.17 upgrade when prompted, or the OS is continuing to use the old drivers which it has cached somewhere. Try reinstalling the Atmel drivers or manually pointing Windows to the folder containing the new 64-bit compatible INF.

– Dean

 

Hi Dean,

I don’t think that’s the problem as this is a freshly installed OS, with a fresh install of AVRStudio 4.17.

I’ll keep fiddling and see if I can figure it out.

Regards,

Mike

 

Mike,

Let me know if you get it to work. On the upside, last night I committed the first working revision of the code, which can perform all the basic ISP tasks. Still to come: support for programming at speeds under 125KHz, and reversed/shorted target line detection.

– Dean

 

Hi again Dean,

Alright, after some fiddling the driver now installs on 64-bit Windows. I had to copy windrvr6.sys, SComm.dll and difxapi.dll from C:\Program Files (x86)\Atmel\AVR Tools\usb64 to C:\Windows\System32\drivers. I also had to copy AtmelUsb.cat and wd1001.cat from C:\Program Files (x86)\Atmel\AVR Tools\usb64 to C:\Windows\System32\catroot\{F750E6C3-38EE-11D1-85E5-00C04FC295EE}. Then In Device Manager I uninstalled the existing “faulty” device, and scanned for new hardware and it installed fine. (I guess the GUID folder would be different on each machine – I had two folders with GUID names, but one was empty so I just copied into the other one that was full of other cat files).

I’m sure the AVR Studio setup should have done that, so maybe they’ll fix it in a later version.

However, it still seems to not be quite working as expected. As I mentioned above, I now have the device showing correctly in Device Manager. If I now go into AVR Studio and select Tools->Program AVR->Connect and ensure that “AVRISP mkii” is selected in the “Platform Box” and “USB” is selected in the “Port” box it comes back with “Connect failed” every time. Is that all I should have to do, or have I missed some step?

Finally, could you please let us know the pinout for the ISP header so that I can wire it up and try some real programming once it’s working (confidence!!).

Thanks & regards,

Mike

 

Actually, don’t worry about the pinout – that was just me being dumb – of course it’s the SPI interface, with the reset line defined in the makefile.

As for the 64-bit problems, all I can put it down to is that somehow AVRStudio can’t talk to the USB device in 64-bit mode. I installed “XP Mode” (32-bit) in Windows 7 x64 and it works just fine from within the VM. It seems strange – I would have thought that once a driver was installed correctly in 64-bit mode then any 32 or 64-bit application should be able to talk to it. However there are a few threads floating around on the internet of people having the same issue with a real AVRISPii in 64-bit, so it makes me wonder why Atmel bothers supplying 64-bit USB drivers which a) don’t install without manually fiddling with file locations, and then b) don’t work with AVRStudio.

Maybe it’s just my weird setup :-)

Regards,

Mike

 

Mike,

Yes, it’s standard SPI -> ISP pinout, which means direct SPI-SPI connections for most devices. The /RESET pin and VTARGET measurement ADC channel (for USB AVRs with an ADC) are defined in the makefile, as you’ve seen.

One caveat at the moment is that you cannot program devices running below 500KHz or so, until I implement software SPI for the lower programming modes.

Please let me know if you succeed in hooking it up to and programming a target — I’d like some independent feedback. Don’t forget to list what USB AVR you tried it on!

– Dean

 

Hi Dean,

I got it going using a Teensy, which uses the AT90USB162. I was having a lot of problem with it timing out when going into Programming mode, which I finally traced to the V2Protocol_ChangeTargetResetLine function.

In the “else” clause you’ve got the DDR statement after the PORT statement. I changed them to the other way around (which makes more sense), and everything works fine now.

I’ll do some more tests and let you know if I find anything.

Regards,

Mike

 

Mike,

Quite right – it should turn off the port driver before it changes the pin logic – I’ll fix that in the SVN. Thanks for testing, great to know it’s working for you!

Cheers!
– Dean

 

Hi again Dean,

Sorry, I spoke too soon. One more issue that I found was in the V2Protocol_WaitWhileTargetBusy function. You seem to have left out a byte. It should send 0xf0 0x00 0x00 0x00 (4 bytes) according to the spec, but you’re only sending 3.

However, there’s one last thing I can’t get working, and it’s a weird one. I can erase the chip, read from flash, read fuse bytes etc, but I can’t program the flash.

In the course of debugging, I changed the programming function to do nothing but return a status of STATUS_CMD_OK, but AVRISP still claims that it “FAILED!”.

The output from AVRISP is:

Getting isp parameter.. SD=0x06 .. OKOK
Reading FLASH input file.. OK
Setting mode and device parameters.. OK!
Entering programming mode.. OK!
Programming FLASH .. FAILED!
Leaving programming mode.. OK!

Here’s my debug version of the function:

static void V2Protocol_Command_ProgramMemory(uint8_t V2Command)
{
struct
{
uint16_t BytesToWrite;
uint8_t ProgrammingMode;
uint8_t DelayMS;
uint8_t ProgrammingCommands[3];
uint8_t PollValue1;
uint8_t PollValue2;
uint8_t ProgData[512];
} Write_Memory_Params;

//Endpoint_Read_Stream_LE(&Write_Memory_Params, 9);

Endpoint_Write_Byte(V2Command);
Endpoint_Write_Byte(STATUS_CMD_OK);

Endpoint_ClearIN();
}

Uncommenting the line causes the USB device to disappear off the bus (thereby causing Leaving Programming Mode to also fail), so it’s something pretty major.

I’m stumped by that – maybe you have some idea?

Regards,

Mike

 

Sorry, I forgot two lines after the Endpoint_Read_Stream line:

Endpoint_ClearOUT();
Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);

However they don’t affect the problem – it still fails.

I also did some debugging by lighting the LED on the Teensy at different points in the code. If the Endpoint_Read_Stream line is uncommented, and the LED lighting command is the next line it doesn’t light. So the program is definitely crashing in that command.

 

Mike,

The WaitWhileBusy *does* transfer all four bytes — three inside the loop, and one inside the while condition (the call to SPI_ReceiveByte(), which sends a dummy 0x00 and returns the received byte from the slave). I’ll make that a little more explicit in the next revision.

As for the other issue, try changing this:

uint8_t ProgData[512];

Inside the Write_Memory_Params to this:

uint8_t ProgData[256];

Which will fix the problem (I hope) — the smaller USB AVRs have only 512 bytes of RAM in them so that was blowing the stack if the compiler was preallocating. I had similar issues to you with the PROGRAM function – it seems the PC driver is very fussy about how fast the data is read out into the device, hence the buffering. As a side note, you can’t just discard the one OUT packet, you need to call Endpoint_Discard_Stream(), as the PC driver will complain if every OUT packet it tries to send is not ACK’d by the device.

– Dean

 

Hi Dean,

You’re right – I hadn’t realised that the SPI_ReceiveByte sent a dummy byte. But for me at least the Erase command would fail until I added the fourth SPI_SendByte in the WaitWhileTargetBusy function. So that led me to look a bit more closely at it, which then led me to the TARGET_BUSY_TIMEOUT_MS parameter. In my case I have to increase that to 250 for it to erase reliably. Also, with that parameter increased the programming now works as well!! Yay!

I did actually finally stumble on the size of the ProgData array about 2am this morning. Again, you’re right, and reducing it to 256 stops us stomping on the stack and crashing the whole thing. My question is what size it can be reduced to? The NumBytes field is two bytes long, which implies that the data sent for programming can be larger than 256. However in my tests with a ATTiny2313, AVRISP is only sending 64 byte packets. Do you know under what circumstances it may send larger packets? I’m concerned that for larger AVRs it may send packets bigger than 256 bytes, and then we’re out of luck if using a AT90USB162. Perhaps you should put a check in the code to fail gracefully if the number of bytes sent by AVRISP is greater than our buffer.

Anyway, it all seems to be finally working now. I’ve only tested programming an ATTINY2313 and and ATMEGA48, so perhaps others can try some of the larger chips.

Thanks for all your help. My parallel port programmer is now officially ready to be binned :-)

Regards,

Mike

 

Mike,

> Thanks for all your help. My parallel port programmer is now officially ready to be binned :-)

Excellent, that’s one happy “customer”, then :). Glad you’re getting some use out of the project so soon — hopefully I’ll be able to add in some even better enhancements soon.

> So that led me to look a bit more closely at it, which then led me to the TARGET_BUSY_TIMEOUT_MS parameter. In my case I have to increase that to 250 for it to erase reliably.

There’s no documented time for timeouts, so I just took a guess. I think I’ll increase it to a second or so, since that should well and truly cover all bases while still making error reporting snappy in the case of a target communication error.

> Again, you’re right, and reducing it to 256 stops us stomping on the stack and crashing the whole thing.

I’ve been developing on the AT90USB647, which has much more RAM, and I didn’t think about the smaller USB AVRs when setting that struct element’s size.

> My question is what size it can be reduced to? The NumBytes field is two bytes long, which implies that the data sent for programming can be larger than 256.

I’ve seen devices with page sizes of at least 128 bytes, and I think 256 byte paged devices exist. Haven’t heard of anything larger than that, but I was originally playing it safe. True, the field is double-byte wide, but only one page will be sent to the device at the one time — so it’s limited by the page size of the target. What will be interesting to find out however would be the number of bytes sent in word mode, where the page size is irrelevant and the host can send any number of bytes. That’s where things could potentially fall down, as the code has to buffer the incoming data before operating on it or the transaction fails.

> Perhaps you should put a check in the code to fail gracefully if the number of bytes sent by AVRISP is greater than our buffer.

I’ll add in a check to return STATUS_CMD_FAILED when the number of sent bytes is too large.

Cheers!
– Dean

 

In terms of hardware, I’ll share what I used in case it’s useful to anyone else. I was previously using the Parallel Port programmer at the bottom of this page http://www.futurlec.com/ET-AVR_Stamp.shtml. I am also using the Teensy board from http://www.pjrc.com/teensy to load Dean’s code on.

I’ve kept using the same parallel port board, but hooked it up to the Teensy instead of the parallel port, as the board already has all the current limiting resistors, LEDs and buffers on it. It’s target-powered, meaning that you can use it on 3.3V and 5V systems (just don’t connect the VCC line from the Teensy to the programming board, but do connect the GND line).

If anyone wants to build their own circuit, the schematic for the board is at http://www.ett.co.th/download/03AVR/03A09/ET_AVR%20ISP_Schematic.pdf. The ET-CAB10P connector is the one that goes to the Teensy, and the ET-PSPI connector goes to the target chip.

I’m sure there are more complex boards that could be made, but this works fine for me.

Regards,

Mike

 

If you reload the original bootloader onto the Teensy, you can software update the programmer via the USB also, meaning you really can bin the parallel port dongle.

– Dean

 

Yeah, that’s what I’m doing. I’m just reusing the buffer part of the old parallel programmer to interface between the teensy programmer and the target chip. I could just connect the teensy directly to the target chip, but that would limit me to 5V targets. Also, best practice says to put 100R resistors on all lines, so by resusing the buffer this way I’ve got a pre-built interface board that can program 3.3V targets, and gives me nice isolation from the 5V teensy.

Mike

 

Hi Dean,

Just an update on the x64 issue. I finally got to the bottom of the problem, and the programmer is now working natively in Windows 7 x64.

The root cause of the issue is that the wdreg.exe program supplied by Jungo to install the USB drivers seems to get confused in Windows 7 x64. If you run it manually, it reports “Error: Cannot run an x86 build of this utility on x64 platform”. I can only assume that this did not happen on Vista x64, but don’t know for sure.

Anyway, as a result of this the x64 USB drivers fail to install when AVRStudio is installed.

I already mentioned above the steps that I had to go through to get the AVRISPmkii to show up in Device Manager, and this still applies. However, in comparing my Device Manager with the working one in XP 32-bit I noticed that there is a device “WinDriver” under the Jungo heading in XP. This wasn’t present in x64 Windows 7.

I tried downloading the updated Jungo Driver from their site after filling out a stupid form, but this showed the same error upon running wdreg.exe.

Finally I just went to Device Manager, right-clicked on the root node and selected “Install Legacy Hardware” and pointed it at the Jungo Windriver .inf file. (I pointed it at the one I had just downloaded, but I would assume it would work with the Atmel supplied ones.) That step then successfully installed the Windriver entry into Device Manager, and everything just worked from there.

So, in summary, people need to make sure there are two entries in Device Manger under the Jungo heading – “WinDriver”, and “AVRISP mkii”.

Hope this helps someone.

Regards,

Mike

 

Leave a Reply

 
(will not be published)
 
 
Comment
 
 

 

Vital Stats

  • 25 Years Old
  • Australian
  • Lover of embedded systems
  • Firmware engineer at LIFX
  • Self-Proclaimed Geek