static uchar usbIsReset; /* = 0; USB bus is in reset phase

General discussions about V-USB, our firmware-only implementation of a low speed USB device on Atmel's AVR microcontrollers
Post Reply
stf92
Rank 1
Rank 1
Posts: 21
Joined: Sat Jan 11, 2014 5:09 pm

static uchar usbIsReset; /* = 0; USB bus is in reset phase

Post by stf92 » Mon Jan 13, 2014 2:02 pm

Hi: This is the declaration of usbIsReset, in usbdrv.c (This is a version from 2008, so perhaps this variable no longer exists):

Code: Select all

static uchar    usbIsReset;             /* = 0; USB bus is in reset phase */

I think the comment is wrong. usbIsReset = 0 when out of reset. Am I right? Another question is this: what is it used for? Only to set usbDeviceId and usbNewDeviceId to zero? And by the way: these two variables are actually the address field of the package, are they not?

blargg
Rank 3
Rank 3
Posts: 102
Joined: Thu Nov 14, 2013 10:01 pm

Re: static uchar usbIsReset; /* = 0; USB bus is in reset p

Post by blargg » Tue Jan 14, 2014 6:57 am

I couldn't find that variable in several of the 2008 versions. From the comment, it looks more like it's just trying to emphasize that static objects in C are initialized to 0 if no initializer is present. In other versions there's a local static for calling a user-defined reset handler only once, and the variable is used to keep track of whether it's been called, so maybe this is for that purpose.

stf92
Rank 1
Rank 1
Posts: 21
Joined: Sat Jan 11, 2014 5:09 pm

Re: static uchar usbIsReset; /* = 0; USB bus is in reset p

Post by stf92 » Fri Jan 17, 2014 7:25 am

blargg wrote:I couldn't find that variable in several of the 2008 versions. From the comment, it looks more like it's just trying to emphasize that static objects in C are initialized to 0 if no initializer is present. In other versions there's a local static for calling a user-defined reset handler only once, and the variable is used to keep track of whether it's been called, so maybe this is for that purpose.


Thanks blargg. Let's change usbIsReset by another variable: usbDeviceId, which may be present in newer versions. This variable is so declared in usbdrv.c:

Code: Select all

volatile char      usbDeviceId;

And my question is now another one: this variable needs to be zero when control first enters the external interrupt service routine, but it is set to zero nowhere in either usbdrv.c or usbdrvasm.S. It is no other thing than the device address, which must be zero when starting enumeration. How can the declaration above make the variable initial value zero? In C, all uninitialized global variables are zero when the program is loaded (from disk). But here, after turning on power, the RAM is in an aleatory state!

The sources I am using are not among the versions listed in this site. I am, however, giving you a link, http://www.filedropper.com/takefuji-213, coded in 2004 by Christian Starkjohann, except the app, da.c, which by its very simplicity is easy to analyze, in case you care to skim it.

stf92
Rank 1
Rank 1
Posts: 21
Joined: Sat Jan 11, 2014 5:09 pm

Re: static uchar usbIsReset; /* = 0; USB bus is in reset p

Post by stf92 » Sat Jan 18, 2014 4:08 am

The why:
For a program running from the ROM of a microcontroller there likely is no loader, and the task of zeroing BSS would fall to the program's runtime startup routine (crt0 in the old days). According to the avr-libc manual, you have the option of placing uninitialized variables in the .bss section (which should be all zero) or the .noinit section, which is a .bss subset that does not get zeroed on startup.

This quotation is from linuxquestions.org. I did not use that option. Do

Code: Select all

 avr-gcc -I. -c -S -mmcu=<avr device> usbdrv.c
. It outputs usbdrv.o and usbdrv.s. The latter is an assembler source, the C source file translated into assembler. Looking into it, you'll see

Code: Select all

 
.global __do_copy_data
.global __do_clear_bss

The global variable under discussion is declared in usbdrv.c:

Code: Select all

volatile char      usbDeviceId;

This variable is used, but not declared, in usbdrvasm.S. But gcc (or avr-gcc, it's the same) considers all undeclared variables in an assembler source as externals. So, in usbdrv.s, it looks like this:

Code: Select all

       .comm   usbDeviceId,1,1

Now, if common variables are taken as globals by gcc, we have that usbDeviceId debuts as zero in the executable! The code to clear the .bss section CANNOT be seen in the assembler sources generated by gcc. It lies in some library and put ahead of the programmer's code by the linker. What do you know?

cpldcpu
Rank 2
Rank 2
Posts: 44
Joined: Sun Nov 10, 2013 11:26 am

Re: static uchar usbIsReset; /* = 0; USB bus is in reset p

Post by cpldcpu » Sat Jan 18, 2014 6:38 am

The AVR-LIBC erases the the bss section before entering main. You can actually see it when disassembling:

This is just an arbitrary example:

>avr-objdump -d -S main.bin >main.lss

Code: Select all

000017fa <__do_clear_bss>:
    17fa:   20 e0          ldi   r18, 0x00   ; 0
    17fc:   a0 e6          ldi   r26, 0x60   ; 96
    17fe:   b0 e0          ldi   r27, 0x00   ; 0
    1800:   01 c0          rjmp   .+2         ; 0x1804 <.do_clear_bss_start>

00001802 <.do_clear_bss_loop>:
    1802:   1d 92          st   X+, r1

00001804 <.do_clear_bss_start>:
    1804:   ac 38          cpi   r26, 0x8C   ; 140
    1806:   b2 07          cpc   r27, r18
    1808:   e1 f7          brne   .-8         ; 0x1802 <.do_clear_bss_loop>
Last edited by cpldcpu on Sat Jan 18, 2014 7:54 am, edited 1 time in total.

stf92
Rank 1
Rank 1
Posts: 21
Joined: Sat Jan 11, 2014 5:09 pm

Re: static uchar usbIsReset; /* = 0; USB bus is in reset p

Post by stf92 » Sat Jan 18, 2014 7:00 am

Fantastic! Thanks cpldcpu.

Post Reply