Search code examples
cassemblyembeddedmsp430atmega

how to find official information on the chip reserved addresses and magic bits?


How can i find from the chip manufacturer the list of magic addresses for several chips? with decent explanations of the values it supports?

I couldn't even figure out the term to call/search for it.

just starting in embedded programming. there's tons of magic bits i have to set to all kinds of things.

usually i'd encounter something:

MOV BLKMGC 0x01

or

REO034 = 0x80; // stops all onboard leds, boot freebsd, makes coffee, do laundy.
               // use 0x81 if you have more white clothes than color ones.

which sometimes has comments explaining what they are doing. I'm mostly taking notes of all of those i find in sample codes. The ones for msp430 launchpad usually are written by nice verbose people with lots of comments and i can even find some of the address maps on the chip family notes, but hardly a comprehensible list. chips more common on Arduinos leaves even more be desired when trying to fully understand that. (granted, i'm still not sure how to search for it :)

The best place i found so far is the header file for the chip i'm using... but even so, take this example:

 void main(void) {
    WDTCTL = WDTPW + WDTHOLD;                 // Stop Watch Dog Timer
    // how 99% of msp430 programs start.

now the header file:

#define WDTCTL_               0x0120    /* Watchdog Timer Control */
sfrw(WDTCTL, WDTCTL_);
/* The bit names have been prefixed with "WDT" */
#define WDTIS0              (0x0001)
#define WDTIS1              (0x0002)
#define WDTSSEL             (0x0004)
#define WDTCNTCL            (0x0008)
#define WDTTMSEL            (0x0010)
#define WDTNMI              (0x0020)
#define WDTNMIES            (0x0040)
#define WDTHOLD             (0x0080)

#define WDTPW               (0x5A00)

/* WDT-interval times [1ms] coded with Bits 0-2 */
/* WDT is clocked by fSMCLK (assumed 1MHz) */
#define WDT_MDLY_32         (WDTPW+WDTTMSEL+WDTCNTCL)                         /* 32ms interval (default) */
#define WDT_MDLY_8          (WDTPW+WDTTMSEL+WDTCNTCL+WDTIS0)                  /* 8ms     " */
#define WDT_MDLY_0_5        (WDTPW+WDTTMSEL+WDTCNTCL+WDTIS1)                  /* 0.5ms   " */
#define WDT_MDLY_0_064      (WDTPW+WDTTMSEL+WDTCNTCL+WDTIS1+WDTIS0)           /* 0.064ms " */
/* WDT is clocked by fACLK (assumed 32KHz) */
#define WDT_ADLY_1000       (WDTPW+WDTTMSEL+WDTCNTCL+WDTSSEL)                 /* 1000ms  " */
#define WDT_ADLY_250        (WDTPW+WDTTMSEL+WDTCNTCL+WDTSSEL+WDTIS0)          /* 250ms   " */
#define WDT_ADLY_16         (WDTPW+WDTTMSEL+WDTCNTCL+WDTSSEL+WDTIS1)          /* 16ms    " */
#define WDT_ADLY_1_9        (WDTPW+WDTTMSEL+WDTCNTCL+WDTSSEL+WDTIS1+WDTIS0)   /* 1.9ms   " */
/* Watchdog mode -> reset after expired time */
/* WDT is clocked by fSMCLK (assumed 1MHz) */
#define WDT_MRST_32         (WDTPW+WDTCNTCL)                                  /* 32ms interval (default) */
#define WDT_MRST_8          (WDTPW+WDTCNTCL+WDTIS0)                           /* 8ms     " */
#define WDT_MRST_0_5        (WDTPW+WDTCNTCL+WDTIS1)                           /* 0.5ms   " */
#define WDT_MRST_0_064      (WDTPW+WDTCNTCL+WDTIS1+WDTIS0)                    /* 0.064ms " */
/* WDT is clocked by fACLK (assumed 32KHz) */
#define WDT_ARST_1000       (WDTPW+WDTCNTCL+WDTSSEL)                          /* 1000ms  " */
#define WDT_ARST_250        (WDTPW+WDTCNTCL+WDTSSEL+WDTIS0)                   /* 250ms   " */
#define WDT_ARST_16         (WDTPW+WDTCNTCL+WDTSSEL+WDTIS1)                   /* 16ms    " */
#define WDT_ARST_1_9        (WDTPW+WDTCNTCL+WDTSSEL+WDTIS1+WDTIS0)            /* 1.9ms   " */

No explanation of the individual bits, no ready-made combination with the most common one.

bonus rant question

since it will always be compiled on powerful, mostly idle, personal computers, why do all compilers/IDE opt to just mimic the user friendliness of bare metal? isn't there tons of better formats to do that? if i'm not going crazy on performance, do i have to know for mundane coding that setting address 0x0120 with the value 0x5A80 stops the watch dog timer? can't the header files/IDE make it be watch_dog_timer( STOP ); to me?


Solution

  • This information is available in the data sheets from the manufacturer. Not all chips have available data sheets1, so keep that in mind when you pick out a chip.

    For an example, let's look at the ATmega48. This is a simple chip with a nice set of basic peripherals.

    1. Go to the manufacturer's website and find the product page. You can do a search for it on their website, or you can even use Google, but I've had the most success just clicking through links on the manufacturer's webpage. Go to the "documents" section of the page.

      For the ATmega48, the documents are available at http://www.atmel.com/devices/ATMEGA48.aspx?tab=documents

    2. Download the appropriate PDF file. This will probably be called a "datasheet" or a "user manual". It is definitely not an "application note" or an "overview". If the file is smaller than about a meg or less than a hundred pages long, it's probably not the right file.

      For the ATmega48, the document is called "ATmega48/88/168 Complete"

    3. The "magic addresses" are called registers. These are IO registers or peripheral registers, not the kind of registers you use when writing user-space programs. Registers are generally unique, and can be read-only, write-only, or read-write.

      For the ATmega48, you can see a list of all registers in section 31 "Register summary". A description of how to use each register can be found under the section describing the relevant peripheral. For example, the GPIO registers are described in section 14 "I/O-ports", with example code both in assembly and C.

    Bonus rant: If you want to write watch_dog_timer( STOP ); in your code, you can define the necessary macros and/or functions yourself (preferably functions, unless your compiler is no good, which happens sometimes with embedded systems2).

    And I hope you're being sarcastic when you say that bare-metal programming is "user-friendly".

    Footnotes:

    1: For example, you can't get the data sheet for the chip on the Raspberry Pi without a large order and an NDA.

    2: In my experience, you often want to choose a chip because it has good compiler support, rather than try to find a good compiler for the chip you already have. At least, if you're a hobbyist. GCC targets Atmel and ARM, which is positively luxurious compared to some of the trashy IDEs I've used.