ATtiny85 self programming flash.

General discussions about V-USB, our firmware-only implementation of a low speed USB device on Atmel's AVR microcontrollers
Post Reply
pe0fko
Posts: 5
Joined: Mon Sep 07, 2009 2:36 pm

ATtiny85 self programming flash.

Post by pe0fko » Fri Feb 19, 2010 5:06 pm

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.

pe0fko
Posts: 5
Joined: Mon Sep 07, 2009 2:36 pm

Re: ATtiny85 self programming flash.

Post by pe0fko » Sat Feb 20, 2010 9:22 pm

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:

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.

christian
Objective Development
Objective Development
Posts: 1443
Joined: Thu Nov 09, 2006 11:46 am

Re: ATtiny85 self programming flash.

Post by christian » Sun Feb 28, 2010 6:47 pm

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.

uchar
Posts: 15
Joined: Wed Oct 28, 2009 12:05 pm

Re: ATtiny85 self programming flash.

Post by uchar » Thu Mar 04, 2010 3:11 pm

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.

christian
Objective Development
Objective Development
Posts: 1443
Joined: Thu Nov 09, 2006 11:46 am

Re: ATtiny85 self programming flash.

Post by christian » Thu Mar 04, 2010 4:44 pm

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.

uchar
Posts: 15
Joined: Wed Oct 28, 2009 12:05 pm

Re: ATtiny85 self programming flash.

Post by uchar » Fri Mar 05, 2010 6:01 pm

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?

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 *)&currentAddress, 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 *)&currentAddress, 4);
    return isLast;
}

christian
Objective Development
Objective Development
Posts: 1443
Joined: Thu Nov 09, 2006 11:46 am

Re: ATtiny85 self programming flash.

Post by christian » Fri Mar 05, 2010 6:12 pm

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.

uchar
Posts: 15
Joined: Wed Oct 28, 2009 12:05 pm

Re: ATtiny85 self programming flash.

Post by uchar » Sat Mar 06, 2010 12:27 am

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.

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.

christian
Objective Development
Objective Development
Posts: 1443
Joined: Thu Nov 09, 2006 11:46 am

Re: ATtiny85 self programming flash.

Post by christian » Sat Mar 06, 2010 6:16 pm

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.

pe0fko
Posts: 5
Joined: Mon Sep 07, 2009 2:36 pm

Re: ATtiny85 self programming flash.

Post by pe0fko » Tue Mar 30, 2010 4:15 pm

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

EmbeddedCreations
Posts: 4
Joined: Sun May 13, 2012 11:37 pm

Re: ATtiny85 self programming flash.

Post by EmbeddedCreations » Sun May 13, 2012 11:41 pm

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/

christian
Objective Development
Objective Development
Posts: 1443
Joined: Thu Nov 09, 2006 11:46 am

Re: ATtiny85 self programming flash.

Post by christian » Tue May 15, 2012 11:15 am

Thanks a lot for this great port to the ATTiny85!

Post Reply