ATtiny85 self programming flash.
ATtiny85 self programming flash.
I try to self program the flash of the tn85 from the usbFunctionWrite() or usbFunctionSetup() function.
I can verify the programming is done by reading the page back.
Only after the programming instruction (spm) I lost the device for a short time. The libusb-win32 call will return a -5 error (Device not ready), after some time (hundred ms?) the device is ready again (no enumeration is done). The page erase and programming will cost a 9ms and will halted the cpu!
Is there a way to save program the flash and keep a stable usb connection, or did I do something wrong?
I use v-usb version 20090822 and libusb-win32 version 0.1.12.2.
Thanks for reading
Fred Krom.
I can verify the programming is done by reading the page back.
Only after the programming instruction (spm) I lost the device for a short time. The libusb-win32 call will return a -5 error (Device not ready), after some time (hundred ms?) the device is ready again (no enumeration is done). The page erase and programming will cost a 9ms and will halted the cpu!
Is there a way to save program the flash and keep a stable usb connection, or did I do something wrong?
I use v-usb version 20090822 and libusb-win32 version 0.1.12.2.
Thanks for reading
Fred Krom.
Re: ATtiny85 self programming flash.
I did some test (again) and don't expect it is the time of programming the flash. Did enter a _delay_ms(30) in place of the programming part and it run's OK.
The code in usbFunctionSetup I use is:
Still get the libusb error code -5 ("USB Error -5: usb_control_msg: sending control message failed, win error: A device attached to the system is not functioning.")
Fred Krom.
The code in usbFunctionSetup I use is:
Code: Select all
if (rq->bRequest == 1)
{
uint8_t i;
uint16_t patroon = rq->wValue.word;
uint16_t address = rq->wIndex.word;
cli();
boot_page_erase(address);
for (i = 0; i < SPM_PAGESIZE; i += 2)
boot_page_fill(i, patroon);
boot_page_write(address);
sei();
}
Still get the libusb error code -5 ("USB Error -5: usb_control_msg: sending control message failed, win error: A device attached to the system is not functioning.")
Fred Krom.
Re: ATtiny85 self programming flash.
Since the Tiny85 does not have read-while-write capability, the CPU is halted during programming. This means that not even interrupts (such as the USB interrupt) can execute. The host won't receive any responses to USB requests during this time.
You might get around the problem if you ensure that all pending USB communication is done before you flash the data. Then wait for 10 ms before you resume USB communication. Note that you must not flash the data from usbFunctionWrite(), only store the data and return with success. After the host has read the status, flash the data from the main loop.
You would still get an error if the operating system wants to read descriptors during this time, though.
You might get around the problem if you ensure that all pending USB communication is done before you flash the data. Then wait for 10 ms before you resume USB communication. Note that you must not flash the data from usbFunctionWrite(), only store the data and return with success. After the host has read the status, flash the data from the main loop.
You would still get an error if the operating system wants to read descriptors during this time, though.
Re: ATtiny85 self programming flash.
Respected Christian!
I use an example hid-data and I too try to write the data in memory of programs - in area NRWW. I use functions boot_page_erase, boot_page_fill and boot_page_write which are in function boot_program_page.
Function boot_program_page is placed in bootloader area.
It is called from function usbFuctionWrite.
But the host program produces an error - Communication error with device. But the microcontroller writes the data in memory of programs successfully.
Prompt please in what there can be a reason?
I am sorry for my English.
I use an example hid-data and I too try to write the data in memory of programs - in area NRWW. I use functions boot_page_erase, boot_page_fill and boot_page_write which are in function boot_program_page.
Function boot_program_page is placed in bootloader area.
It is called from function usbFuctionWrite.
But the host program produces an error - Communication error with device. But the microcontroller writes the data in memory of programs successfully.
Prompt please in what there can be a reason?
I am sorry for my English.
Re: ATtiny85 self programming flash.
Whey you receive the data in (e.g.) usbFunctionWrite(), the last USB transfer is not complete. The host wants to read a zero byte block as a kind of ACK. The host polls for this reply while you are in usbFunctionWrite(). If you block the CPU during this time, the host won't receive a NAK to its polling and thus produce an error.
You must ensure that the transfer is complete before you block the CPU. HID for this purpose is not a good idea because the host polls the interrupt endpoint in any case. I'd recommend a custom class device.
You must ensure that the transfer is complete before you block the CPU. HID for this purpose is not a good idea because the host polls the interrupt endpoint in any case. I'd recommend a custom class device.
Re: ATtiny85 self programming flash.
Thanks for the answer, Christian.
On your site there is an example - bootloadHID - http://www.obdev.at/products/vusb/bootloadhid.html
I have checked up - it works, but all functions are called from usbFunctionWrite.
Explain please why this example works?
On your site there is an example - bootloadHID - http://www.obdev.at/products/vusb/bootloadhid.html
I have checked up - it works, but all functions are called from usbFunctionWrite.
Explain please why this example works?
Code: Select all
uchar usbFunctionWrite(uchar *data, uchar len)
{
union {
addr_t l;
uint s[sizeof(addr_t)/2];
uchar c[sizeof(addr_t)];
} address;
uchar isLast;
address.l = currentAddress;
if(offset == 0){
DBG1(0x30, data, 3);
address.c[0] = data[1];
address.c[1] = data[2];
#if (FLASHEND) > 0xffff /* we need long addressing */
address.c[2] = data[3];
address.c[3] = 0;
#endif
data += 4;
len -= 4;
}
DBG1(0x31, (void *)¤tAddress, 4);
offset += len;
isLast = offset & 0x80; /* != 0 if last block received */
do{
addr_t prevAddr;
#if SPM_PAGESIZE > 256
uint pageAddr;
#else
uchar pageAddr;
#endif
DBG1(0x32, 0, 0);
pageAddr = address.s[0] & (SPM_PAGESIZE - 1);
if(pageAddr == 0){ /* if page start: erase */
DBG1(0x33, 0, 0);
#ifndef TEST_MODE
cli();
boot_page_erase(address.l); /* erase page */
sei();
boot_spm_busy_wait(); /* wait until page is erased */
#endif
}
cli();
boot_page_fill(address.l, *(short *)data);
sei();
prevAddr = address.l;
address.l += 2;
data += 2;
/* write page when we cross page boundary */
pageAddr = address.s[0] & (SPM_PAGESIZE - 1);
if(pageAddr == 0){
DBG1(0x34, 0, 0);
#ifndef TEST_MODE
cli();
boot_page_write(prevAddr);
sei();
boot_spm_busy_wait();
#endif
}
len -= 2;
}while(len);
currentAddress = address.l;
DBG1(0x35, (void *)¤tAddress, 4);
return isLast;
}
Re: ATtiny85 self programming flash.
This works on devices which have Read-While-Write capability (probably all devices with a boot loader section). It does NOT work on the ATTiny85.
Re: ATtiny85 self programming flash.
Excuse, has forgotten to write - I use ATMega8.
I use AVRStudio, in project customisations has specified compiler AVR-GCC. Function boot_program_page is placed in area bootloader.
The host program produces an error - it is returned by function usbhidSetReport.
Tried to write to area NRWW and in area RWW - the error is always.
I hope for your help
P.S. The example from your site (bootloadHID) works for me.
I use AVRStudio, in project customisations has specified compiler AVR-GCC. Function boot_program_page is placed in area bootloader.
Code: Select all
void BOOTLOADER_SECTION boot_program_page (uint32_t page)
{
uint16_t i;
uint8_t sreg;
uint8_t ser_1;
uint8_t ser_2;
uint16_t page_offset = 0;
ser_1 = 0x02;
ser_2 = 0x49;
DDRC = 1; //LED OFF
PORTC = 1;
sreg = SREG;
cli();
eeprom_busy_wait ();
boot_page_erase (page);
boot_spm_busy_wait ();
eeprom_busy_wait ();
boot_page_fill(page + page_offset, ser_1);
boot_spm_busy_wait ();
eeprom_busy_wait ();
boot_page_write(page);
boot_spm_busy_wait ();
eeprom_busy_wait ();
boot_rww_enable ();
boot_spm_busy_wait ();
SREG = sreg;
DDRC = 1; //LED ON
PORTC = 0;
}
uchar usbFunctionWrite(uchar *data, uchar len)
{
DDRC = 1; //LED ON
PORTC = 0;
boot_program_page(0x1ff8);
return 1;
}
The host program produces an error - it is returned by function usbhidSetReport.
Code: Select all
f((err = usbhidSetReport(dev, buffer, sizeof(buffer))) != 0)
{
fprintf(stderr, "error FLASH-write command: %s\n", usbErrorMessage(err));
}
Tried to write to area NRWW and in area RWW - the error is always.
I hope for your help
P.S. The example from your site (bootloadHID) works for me.
Re: ATtiny85 self programming flash.
You keep the interrupts disabled while you do the busy wait. This way you lock out the driver during the write operation. See bootloadHID for an example where to disable interrupts and where to keep them enabled.
Re: ATtiny85 self programming flash.
christian wrote:This means that not even interrupts (such as the USB interrupt) can execute.
Did try a simulation of the program command with a _delay_ms, did not put the cli() sei() around it That did confuse me, that it was running with a long (30ms) delay, but with interrupts on it was still running the low level of usb communication.
christian wrote:After the host has read the status, flash the data from the main loop.
Will try that way, need to find a quiet moment in the loop.
The program is running if ignoring the error on the program command, it will also depend on the error handling of the PC lib I expect. Not that nice programming if I do it that way
Thanks Christian for the comment!!
Fred Krom
-
- Posts: 4
- Joined: Sun May 13, 2012 11:37 pm
Re: ATtiny85 self programming flash.
This thread helped me understand why there wasn't a V-USB based bootloader for the ATtiny85 when I went looking for one. I did figure out how to work around the issues with the ATtiny architecture and updated Christian's USBaspLoader project to have ATtiny85 support. It's still a work in progress, the main thing I'd like to improve is the program size, it's currently taking up 1/3 of the 8kB flash on the ATtiny85.
http://embedded-creations.com/projects/ ... -overview/
http://embedded-creations.com/projects/ ... -overview/
Re: ATtiny85 self programming flash.
Thanks a lot for this great port to the ATTiny85!