0

EDITED AND SHORTENED

My goal is to write the minimum necessary startup-code and linker script "from scratch" for a system which is new to me and reach main(). I only want to use the available documentation. No IDE or code generation. I picked the Attiny 2313. I am not trying to flash the code yet, just cross-compile and link.

The toolchain I am trying to use is avr-gcc, objdump for checking and GNU LD for linking.

The specific questions I want to ask are the following:

  1. Does the compiler already know symbols of fuse bits like CKEL, SUT and SREG? Do I have to declare them myself? I read avr-gcc documentation and gnu-as-documentation.

  2. I found that for avr, a variety of memory-sections is created: .text, .data, .bss, .eeprom, .noinit, .initN, .finiN, .note.gnu.avr.deviceinfo. Should I expect that any of these memory-sections is in use? Or is it even mandatory that all sections are in use?

3
  • In the process of searching for further material, I found a really neat AVR-Assembler-Simulator Commented Oct 23, 2023 at 19:17
  • 2
    You're asking a lot of questions in one post here. It's going to take a big investment if anyone decides to try to write an answer for you. I know the answers to many of your individual questions but I don't feel like digging through our whole post to find every single thing you asked and making sure I address all of them. I suggest asking one question at a time and provide an minimal reproducible example and links to any relevant documentation to show your best attempt to solve the problem yourself. Commented Oct 23, 2023 at 21:51
  • @DavidGrayson After revisiting the question, you are right. I wanted to clarify my status quo, but I agree that there are too many questions Commented Oct 24, 2023 at 8:16

2 Answers 2

3

The GNU tools for AVR come with the convenience that they work from scratch, no need to concoct your own startup code, linker scripts. Just

$ avr-gcc main.c -Os -mmcu=attiny2313 -Wall -o main.elf

and then flash that ELF file using, say, avrdude.

How the Tools are working together

  • Add -v to the command line options. avr-gcc will print which commands it is executing, like calling compiler proper (cc1 or cc1plus), assembler (as) or linker (ld).

  • Add -fverbose-asm -save-temps to see which assembly the compiler is generating (in .s files) and what the pre-processor is generating (in .i for C and .ii for C++).

  • Use objdump to get dis-assembly; you already found that.

  • Add -Wl,-Map,main.map to get a map file. This is a text file that shows locations, which symbol is dragged from which library, etc.

Startup Code

This is a mix of AVR-LibC's gcrt1.S (vector table, setting up SFRs like SP, calling main and exit) and libgcc's lib1funcs.S (setting up .data and .bss, calling static constructors and destructors).

  • If you want to do special stuff, you can provide this as naked asm in one of the .initN sections.

  • If you want own startup code altogether, provide it but link with -nostartfiles. This will still drag the libgcc parts, except you provide your own __do_clear_bss and __do_copy_data or you'll have to link -nodefaultlibs or -nostdlib.

  • If you just want to provide start-up code for some device never seen before, the easiest way is to write / generate the respective avr/io.h parts and add support for the new device to AVR-LibC, which is a one-liner in gen-avr-lib-tree.sh.

  • You may also follow the avr-gcc wiki on Supporting "unsupported" Devices.

Special Function Registers

  • SFRs are defined as macros by #include <avr/io.h>. This header is also fit to work together with the GNU assembler (with some peculiarities wrt. I/O vs. RAM addresses and AVR_SFR_OFFSET).

  • avr-gcc starts every assembly file with e.g.

    __SP_H__ = 0x3e
    __SP_L__ = 0x3d
    __SREG__ = 0x3f
    __tmp_reg__ = 0
    __zero_reg__ = 1
    

    so you can use these without further ado in inline assembly.

  • To use SFRs in inline assembly, pass their address with constraint "n", and use print modifier %i if you want the I/O address.

Linker Scripts

Default linker scripts are shipped with the tools in install path avr/lib/ldscripts/ located in --prefix as of configure.

In almost all cases, the defaults are enough. If not, you can augment them by INCLUDE AFTER <section> etc., see GNU ld documentation.

Notice that the default linker scipts are compiled-in in the ld execuatble, and changing them on file has no effect. Provide your linker description to the linker by means of avr-gcc ... -T <my-ld-script>.

Linking

In almost all cases, you want to link using avr-gcc, not by calling avr-ld directly. For rationale, see for example this answer or this one.

Sign up to request clarification or add additional context in comments.

Comments

2

AVR's have lots unique design descisions which make them very fun to code in assembler. At its core, an AVR cpu does two things: fetch instructions, and execute them. As the device boots up, the program counter points at address 0x0000 (reset vector). And if no jmp/rjmp or some other branching instruction is there, it will fetch the next instruction in address 0x0001 and execute it.

For starting out I would focus on learning the instruction set and especially instructions concerned with Memory (lds, sts, in, out, ld, st, ldi) and don't think about interrupt vectors or any peripherals as it can get overwhelming pretty quick. After that try to make analogues of stuff you know in other languages, like defining a static array and filling it with numbers from 0 to n, simple stuff like that, so that you actually get to successfully compile some programs and have the ability to debug in the simulator (also included in microchip studio)

In general, the concepts you need to focus on are (most important to least):

  1. Arithmetic instructions
  2. Branching (JMP/RJMP/BREQ/BRNE etc)
  3. Volatile Memory instructions (listed above)
  4. Pointers (X,Y,Z And their iusage with ld/st instructions)
  5. The stack pointer (PUSH/POP instructions)
  6. Routines (CALL/RCALL/RET instructions)
  7. Interrupts and interrupt routines (RETI instruction and the vector )

There are many many more concepts to understand. I would also recommend watching some youtube videos for examples of simple code you can compile and debug where someone takes you through some of it step by step.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.