avr_lock(3)

πŸ“¦ version 2.2.1, in fedora 43, fedora 44, opensuse-leap 16.0

πŸ’… avr_lock β€” the lockbit API, bestie

okay so this is avr_lock(3), straight out of the avr-libc manual, and honestly? it's giving "tiny API, huge consequences." sit with me, we're gonna get through it together 🫢


✨ NAME ✨

avr_lock β€” no cap, that's the whole name. iconic minimalism.


🌸 SYNOPSIS 🌸

πŸ’– Detailed Description πŸ’–

πŸŽ€ Introduction πŸŽ€

So the Lockbit API lets you, the user, specify the lockbit settings for the specific AVR device you're compiling for. Those lockbit settings get placed into a special section in the ELF output file, and that happens after linking. periodt.

Programming tools can take advantage of the lockbit info embedded in the ELF file β€” they extract it and figure out whether the lockbits need to be programmed after the Flash and EEPROM memories get programmed. This also means a single ELF file can contain all the info needed to program an AVR. one file, all the lore. obsessed.

To use the Lockbit API, include the <avr/io.h> header file, which automatically includes the individual I/O header file and the <avr/lock.h> file. Those other two files hand you everything you need to set the AVR lockbits. bestie behaviour, fr fr.


πŸ”₯ Lockbit API πŸ”₯

Each I/O header file may define up to 3 macros that control what kinds of lockbits are available to the user.

  • If __LOCK_BITS_EXIST is defined, then two lock bits are available to the user and 3 mode settings are defined for these two bits.
  • If __BOOT_LOCK_BITS_0_EXIST is defined, then the two BLB0 lock bits are available to the user and 4 mode settings are defined for these two bits.
  • If __BOOT_LOCK_BITS_1_EXIST is defined, then the two BLB1 lock bits are available to the user and 4 mode settings are defined for these two bits.
  • If __BOOT_LOCK_APPLICATION_TABLE_BITS_EXIST is defined then two lock bits are available to set the locking mode for the Application Table Section (which is used in the XMEGA family).
  • If __BOOT_LOCK_APPLICATION_BITS_EXIST is defined then two lock bits are available to set the locking mode for the Application Section (which is used in the XMEGA family).
  • If __BOOT_LOCK_BOOT_BITS_EXIST is defined then two lock bits are available to set the locking mode for the Boot Loader Section (which is used in the XMEGA family).

The AVR lockbit modes have inverted values β€” logical 1 for an unprogrammed (disabled) bit, and logical 0 for a programmed (enabled) bit. The defined macros for each individual lock bit represent this in their definition by a bit-wise inversion of a mask. For example, the LB_MODE_3 macro is defined as:

#define LB_MODE_3  (0xFC)
`
ngl that lone backtick at the end is just... there. we don't ask. we reproduce. πŸ™ˆ

To combine the lockbit mode macros together to represent a whole byte, use the bitwise AND operator, like so:

(LB_MODE_3 & BLB0_MODE_2)

<avr/lock.h> also defines a macro that provides a default lockbit value: LOCKBITS_DEFAULT, which is defined to be 0xFF.

See the AVR device specific datasheet for more details about these lock bits and the available mode settings. (yes bestie, the datasheet. it's giving required reading. go.) πŸ“–

A convenience macro, LOCKMEM, is defined as a GCC attribute for a custom-named section of '.lock'.

A convenience macro, LOCKBITS, is defined that declares a variable, __lock, of type unsigned char with the attribute defined by LOCKMEM. This variable allows the end user to easily set the lockbit data. slay.

Note: If a device-specific I/O header file has previously defined LOCKMEM, then LOCKMEM is not redefined. If a device-specific I/O header file has previously defined LOCKBITS, then LOCKBITS is not redefined. LOCKBITS is currently known to be defined in the I/O header files for the XMEGA devices.

πŸ¦‹ API Usage Example πŸ¦‹

Putting all of this together is easy:

#include <avr/io.h>

LOCKBITS = (LB_MODE_1 & BLB0_MODE_3 & BLB1_MODE_4);

int main(void)
{
    return 0;
}

Or:

#include <avr/io.h>

unsigned char __lock __attribute__((section (".lock"))) =
    (LB_MODE_1 & BLB0_MODE_3 & BLB1_MODE_4);

int main(void)
{
    return 0;
}

However there are a number of caveats that you need to be aware of to use this API properly. okay so listen up, this part is the main character πŸ’…

  • Be sure to include <avr/io.h> to get all of the definitions for the API. The LOCKBITS macro defines a global variable to store the lockbit data. This variable is assigned to its own linker section. Assign the desired lockbit values immediately in the variable initialization.
  • The .lock section in the ELF file will get its values from the initial variable assignment ONLY. This means that you can NOT assign values to this variable in functions and the new values will not be put into the ELF .lock section. like... it just won't. πŸ’€
  • The global variable declared in the LOCKBITS macro has two leading underscores, which means it's reserved for the 'implementation' β€” meaning the library β€” so it will not conflict with a user-named variable. bestie is out here avoiding drama. respectful.
  • You must initialize the lockbit variable to some meaningful value, even if it's the default value. This is because the lockbits default to a logical 1, meaning unprogrammed. Normal uninitialized data defaults to all logical zeros. So it is vital that all lockbits are initialized, even with default data. If they are not, then the lockbits may not be programmed to the desired settings and can possibly put your device into an unrecoverable state. 🚨 no pressure though!!!!
  • Be sure to have the -mmcu=device flag in your compile command line and your linker command line, so the correct device is selected and the correct I/O header file gets included when you include <avr/io.h>.

You can print out the contents of the .lock section in the ELF file by using this command line:

avr-objdump -s -j .lock <ELF file>

πŸ‘‘ Author πŸ‘‘

Generated automatically by Doxygen for avr-libc from the source code. (the bots did this one, we just vibed it up ✨)


Version 2.1.0 β€” Sat Jan 29 2022 πŸŽ€

and that's the whole page, bestie. go set those lockbits (carefully!!!), keep your .lock section initialized, and remember: logical 1 = unprogrammed, logical 0 = programmed. iykyk. mwah πŸ’–

πŸ“¦ where this page comes from