Anybody know C?

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

I have to make a couple of changes to a C program.  I haven't used C in decades. 

 

I have C++ code I wish I could make work with a C compiler by making some simple changes.

 

Can this code, and others like it, be made to compile as C?

 

One problem, I suppose, is structs in C++ are automatically types.  In C, structs have to be kicked in the head to make them types.  I guess the same is true of unions.

 

In the following code, Control_b, (capital C) is a type.  It's a union of an 8 bit int called byte, and a bit field called bits.   At the terminating }; that ends the union, the C compiler sez, declaration does not declare anything. 

 

  union Control_b   {
      struct   {
         Register attach                     : 1;  // ATTACH
         Register global_NACK                : 1;  // GNACK
         Register remote_wake_up             : 1;  // RWAKEUP
         Register reserved_3                 : 1;  // Reserved
         Register pullup_held_during_reset   : 1;  // PULLRST
         Register reserved_5_7               : 3;  // Reserved
         } bits;
      Register byte;                      
      };        // <---- C compiler sez, declaration does not declare anything.

   volatile  Control_b control_b;        

 

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

Try

 

  typedef union  {
    struct   {
      Register attach                     : 1;  // ATTACH
      Register global_NACK                : 1;  // GNACK
      Register remote_wake_up             : 1;  // RWAKEUP
      Register reserved_3                 : 1;  // Reserved
      Register pullup_held_during_reset   : 1;  // PULLRST
      Register reserved_5_7               : 3;  // Reserved
    } bits;
    Register byte;
  } Control_b; 

This should create the Control_b type you want.

 

Last Edited: Wed. Jul 22, 2020 - 08:57 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

volatile  union Control_b control_b; 

 

Control_b is a tag and not really a type. You can create a type with typedef as seen above, so could make Control_b a type if wanted.

 

 

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

El Tangas wrote:

Try

 

This should create the Control_b type you want.

 

No worky.  On the first line " typedef union {", I get:

Error        expected specifier-qualifier-list before 'typedef'    

 

 

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

curtvm wrote:

volatile  union Control_b control_b; 

 

Control_b is a tag and not really a type. You can create a type with typedef as seen above, so could make Control_b a type if wanted.

 

 

No worky either.  I get the original error before I get to the line you suggest.

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

That's okay.  I just thought I'd give my idea a try.  There should be some places in the code where the original C author has done something like what I want to do. 

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

steve17 wrote:
No worky.  On the first line " typedef union {", I get:

 

Error        expected specifier-qualifier-list before 'typedef'  

Maybe your compiler doesn't like unnamed unions... I never remember if that's valid or not, I thought it would be ok since you have an unnamed struct inside the union. So maybe this will work:

 

  typedef union Control_b_t {
    struct   {
      Register attach                     : 1;  // ATTACH
      Register global_NACK                : 1;  // GNACK
      Register remote_wake_up             : 1;  // RWAKEUP
      Register reserved_3                 : 1;  // Reserved
      Register pullup_held_during_reset   : 1;  // PULLRST
      Register reserved_5_7               : 3;  // Reserved
    } bits;
    Register byte;
  } Control_b; 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

No.  the first line gets an error.

Error        expected specifier-qualifier-list before 'typedef'    

 

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

I think there is some other error in the source file.  Has the type Register been defined?

 

$ cat zz.c
#include <avr/io.h>

typedef uint8_t Register;

typedef union  {
    struct   {
      Register attach                     : 1;  // ATTACH
      Register global_NACK                : 1;  // GNACK
      Register remote_wake_up             : 1;  // RWAKEUP
      Register reserved_3                 : 1;  // Reserved
      Register pullup_held_during_reset   : 1;  // PULLRST
      Register reserved_5_7               : 3;  // Reserved
    } bits;
    Register byte;
  } Control_b; 

volatile Control_b a, b, c;
$ /usr/bin/avr-gcc -mmcu=atmega328p -c zz.c 
(no errors)

 

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

steve17 wrote:

No.  the first line gets an error.
Error        expected specifier-qualifier-list before 'typedef'    

 

It means that you are withholding something. Everything that has been suggested here is perfectly correct and compiles without any errors. Whatever errors you are getting have nothing to do with the issue at hand. The actual error is elsewhere. Believe it or not, we cannot see the rest of your code from here.

Dessine-moi un mouton

Last Edited: Thu. Jul 23, 2020 - 12:57 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

MattRW wrote:
Has the type Register been defined?
That was my first thought. Presumably it needs something like:

typedef uint8_t Register;

(but surely "Register" - whatever that is - is defined something like this in the original C++ ?)

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

Sorry about the Register thing.  I always include myTypes.h in my code.  Been doing it for 30 years.

 

Register is an 8 bit unsigned int.  I don't know what you guys use for 8 bits.  Something like this:

typedef uint8_t Register;

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

steve17 wrote:
I don't know what you guys use for 8 bits.
stdint.h gives uint8_t for that so I'm not sure why one would choose to hide the fact that it is unsigned and 8 bits wide behind a name like "Register" ?

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

Del

Dessine-moi un mouton

Last Edited: Thu. Jul 23, 2020 - 11:46 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It is an i/o device register.  I believe Atmel does this also. 

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

steve17 wrote:
I believe Atmel does this also. 
At least in the Xmega header files they call it "register8_t" so it retains knowledge of the width in the name and I guess one maybe just assumes a "register" is going to be unsigned? But I'd still prefer just a plain "uint8_t" myself.

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

I can go either way.  The use of the _t though seems stupid to me.  Do you use int_t, char_t and float_t?  What about the names of your classes?  Do they all end in _t?

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

steve17 wrote:
I can go either way.  The use of the _t though seems stupid to me.  Do you use int_t, char_t and float_t?  What about the names of your classes?  Do they all end in _t?
Actually, because of stdint.h, yes, in our coding standard we do suffix "_t" to everything that is a typedef. As MISRA does not allow the use of original base types like "int", "short", etc we don't have a problem with their meaningless type names.

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

>The use of the _t though seems stupid to me

 

The _t is telling you its a type that was defined somewhere, and is not native to the language. It also avoids name collision, unless you have a habit of naming non-type things that end in _t. If you are creating types, then _t is a good way to see that it is a type and not some other thing.

 

 

>Do you use int_t, char_t and float_t?

 

A char/int/float is native to the language so no need to redefine it by making it another type. 

 

 

>It is an i/o device register.  I believe Atmel does this also. 

 

there are probably many variations they do, but this is one-

 

typedef volatile uint8_t register8_t;

 

then they make the struct members volatile and create a define for access (and they typically do not provide bit access for some reason in avr/arm, but do in the pics)

 

typedef struct SOME_struct {

    register8_t CTRLA;

    register8_t CTRLB;

} SOME_t;

 

#define SOME  (*(SOME_t *) 0x0000)

 

but they could just as well do the following, where the volatile is moved to the access point.

 

typedef struct SOME_struct {

    uint8_t CTRLA;

    unsigned char CTRLB;

} SOME_t;

 

#define SOME  (*(volatile SOME_t *) 0x0000)

 

I would do something like-

https://godbolt.org/z/ME4eEj

where the anonymous structs make access nicer

 

 

>I have C++ code I wish I could make work with a C compiler by making some simple changes.

 

You will get better help if you describe what compiler you are dealing with. Sounds like an old compiler.

 

Last Edited: Thu. Jul 23, 2020 - 02:46 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Okay, remembering when I used C, it was confusing, because structs aren't types.

 

I use C++ and that's a different story.  In C++, a struct, a.k.a class, is a type.  This makes understanding the code a lot easier.  We usually call them classes rather than structs, because these things are very much handier than C structs.  C++ programs are basically a collection of classes.  Nobody ends their class/struct names with _t because it serves no purpose.

 

I've been using things like int8 and u_int8 for 35 years.  It's necessary when writing portable code.  I'm glad that the high priests of C have put down their bongs long enough to come up with their own stuff but I'm not switching now.

 

 

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

Quote:

You will get better help if you describe what compiler you are dealing with. Sounds like an old compiler.

I have the latest Atmel Studio.  If I do a "avr-gcc -v", I get

gcc version 4.6.2 (AVR_8_bit_GNU_Toolchain_3.4.0_663)

 

 

Last Edited: Thu. Jul 23, 2020 - 05:10 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The online compiler with ver 4.5.4 works (with only the addition of the union as in post #3)

 

https://godbolt.org/z/ExY93T

(if control_b is a hardware register, then you will have to do something different, as you are now creating a ram var)

 

There are newer versions of the compiler of course, and they are free.

 

 

>I use C++

 

Why not keep using c++. I use c++ for anything that supports it- avr, pic32mm, samd10, nrf52, etc. 

Last Edited: Thu. Jul 23, 2020 - 05:25 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Interesting your code works.  I don't know if I want to find and somehow get Studio to use your compiler version.  I'd probably want to eventually restore my version.  It might be compiler options set in Studio.

 

I hate using C, but I want to put a fairly small fix in LUFA.  The project I have for it doesn't include the C++ compiler.  LUFA seems huge.  It apparently works with all Atmel USB, and with all permutations of the options.  It has folders nested 10 deep. 

 

I think I can find where the author makes the accesses to the USB device that I need to do.  I'll search for those now.

Last Edited: Thu. Jul 23, 2020 - 08:30 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

> I don't know if I want to find and somehow get Studio to use your compiler version.  I'd probably want to eventually restore my version.  It might be compiler options set in Studio.

 

I don't use Studio, but in mplabx I have quite a few compilers of various versions. Basically tell the ide where they are located, and that's it. Then choose whatever version you want, anytime you want, with whatever project you want. I can't imagine Studio couldn't do the same.

 

The latest from Atmelchip-

https://www.microchip.com/mplab/avr-support/avr-and-arm-toolchains-c-compilers

 

I also use avr gcc 7.3 from arduino, and you can find the link to that toolchain with a little bit o digging around (I use 7.3 to get nice c++17 things).

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

steve17 wrote:
... but I want to put a fairly small fix in LUFA.
Thank you; LUFA is FOSS (MIT)

 

"Dare to be naïve." - Buckminster Fuller

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

"Dare to be naïve." - Buckminster Fuller

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

The actual error is elsewhere. Believe it or not, we cannot see the rest of your code from here.

And half a dozen posts later, we still can't see enough of the code to see what's wrong.   :-(

 

Before anonymous structs, we would have done something like:

typedef struct mystruct_ {
    int blah;
    char bar;
} mystruct_t;

 

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

steve17 wrote:
The use of the _t though seems stupid to me.  Do you use ...
steve17 wrote:
I have C++ code

So you are a decades-experienced programmer, and C++ didn't go the stdint route?  Oh, wait:

Fixed width integer types (since C++11)

 

C++

 

Utilities library

 

Type support

 

Types

Defined in header <cstdint>

int8_tint16_tint32_tint64_t

(optional)

signed integer type with width of exactly 8, 16, 32 and 64 bits respectively
with no padding bits and using 2's complement for negative values
(provided only if the implementation directly supports the type)
(typedef)

Didn't paste well; " Defined in header <cstdint> <cstdint>"

 

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.

Last Edited: Fri. Jul 24, 2020 - 01:35 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

LUFA on Github.

 

https://github.com/abcminiuser/lufa

 

clone (on one of my other computers with Ubuntu 20.04, not the one I am typing this).

 

avr-gcc -v
Using built-in specs.
Reading specs from /usr/lib/gcc/avr/5.4.0/device-specs/specs-avr2
COLLECT_GCC=avr-gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/avr/5.4.0/lto-wrapper
Target: avr
Configured with: ../gcc/configure -v --enable-languages=c,c++ --prefix=/usr/lib --infodir=/usr/share/info --mandir=/usr/share/man --bindir=/usr/bin --libexecdir=/usr/lib --libdir=/usr/lib --enable-shared --with-system-zlib --enable-long-long --enable-nls --without-included-gettext --disable-libssp --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=avr CFLAGS='-g -O2 -fdebug-prefix-map=/build/gcc-avr-q39GPj/gcc-avr-5.4.0+Atmel3.6.1=. -fstack-protector-strong -Wformat ' CPPFLAGS='-Wdate-time -D_FORTIFY_SOURCE=2' CXXFLAGS='-g -O2 -fdebug-prefix-map=/build/gcc-avr-q39GPj/gcc-avr-5.4.0+Atmel3.6.1=. -fstack-protector-strong -Wformat ' FCFLAGS='-g -O2 -fdebug-prefix-map=/build/gcc-avr-q39GPj/gcc-avr-5.4.0+Atmel3.6.1=. -fstack-protector-strong' FFLAGS='-g -O2 -fdebug-prefix-map=/build/gcc-avr-q39GPj/gcc-avr-5.4.0+Atmel3.6.1=. -fstack-protector-strong' GCJFLAGS='-g -O2 -fdebug-prefix-map=/build/gcc-avr-q39GPj/gcc-avr-5.4.0+Atmel3.6.1=. -fstack-protector-strong' LDFLAGS='-Wl,-Bsymbolic-functions -Wl,-z,relro' OBJCFLAGS='-g -O2 -fdebug-prefix-map=/build/gcc-avr-q39GPj/gcc-avr-5.4.0+Atmel3.6.1=. -fstack-protector-strong -Wformat ' OBJCXXFLAGS='-g -O2 -fdebug-prefix-map=/build/gcc-avr-q39GPj/gcc-avr-5.4.0+Atmel3.6.1=. -fstack-protector-strong -Wformat '
Thread model: single
gcc version 5.4.0 (GCC)

git clone https://github.com/abcminiuser/lufa
cd lufa
make all
...
avr-objdump -h -d -S -z BootloaderPrinter.elf > BootloaderPrinter.lss
 [NM]      : Extracting SYM file data from "BootloaderPrinter.elf"
avr-nm -n BootloaderPrinter.elf > BootloaderPrinter.sym
 [SIZE]    : Determining size of "BootloaderPrinter.elf"

avr-size --mcu=at90usb1287 --format=avr BootloaderPrinter.elf
AVR Memory Usage
----------------
Device: at90usb1287

Program:    3744 bytes (2.9% Full)
(.text + .data + .bootloader)

Data:        246 bytes (3.0% Full)
(.data + .bss + .noinit)


 [INFO]    : Finished building project "BootloaderPrinter".
make[2]: Leaving directory '/home/rsutherland/Samba/git/lufa/Bootloaders/Printer'
make[1]: Leaving directory '/home/rsutherland/Samba/git/lufa/Bootloaders'

LUFA "make all" operation complete.

That ran a long time, but no errors. It may help to know where you are trying to make changes, e.g. like this link.

 

https://github.com/abcminiuser/lufa/blob/master/LUFA/Drivers/USB/Core/AVR8/USBController_AVR8.c#L46

my projects: https://github.com/epccs

Debugging is harder than programming - don’t write code you can’t debug! https://www.avrfreaks.net/forum/help-it-doesnt-work