Registers - what to write/read??

So this is something that bothered me a lot lately.

Some students were at the robotics club I am part of and some asked me "how do I know what to put in this register?". This was in a PIC that I never, ever used and this were students doing the final project.

I was able to pretty easily help them. Why? Because datasheets are pretty much the same in register description! Some can be worse or better at describing the functional descriptions, elaborate the registers operations and initialization, but all say what are the values to write on registers or what they mean when read.

Now, I am not fond of using register only programming. Actually I discourage it when using newer platforms, your just giving yourself a headache and lose time. But sometimes it is needed! And it's important to know how they work, how to read what they do and how to use them even though you won't use them most of the times! It's important for debugging purposes and when you need more speed or something isn't covered by the libraries.

So this is what the heck do I write/read on a register? It's soooooooooo important to know how to read the tech documents.

For this example I will use a STM32F0 document which is what I am working at the moment.

Now first of all, most (all?) datasheets have 2 things. A register map and a description of each register.

The register map can give you a short description of the register, a "title" or the name itself is self explanatory.

Now there are 2 options. ´

You can have a datasheet with specific for your part and a reference manual with general/common info about a group of parts - in this case the reference manual has the most info about registers and peripherals functions while the datasheet is things like pins functions, packages, electrical characteristics and some general summary of the included peripherals.

The other options is that the datasheet has all that info.

Let's see the case of a STM32F0. Let's use a timer since it's pretty common between MCUs

In this case it has a reference manual and a datasheet separated. In PDF format the reference manual has handy bookmarks! (if you are lucky the MCU you are using has them too on the documents). In this case I don't find the register map very handy to extract a summary about the registers unless you know what the acronyms mean. The bookmarks on the other hand are the best!! Just look this on the Timer 1:

I think all can agree that this is easy to extract the function of each register. We can see for example that there's 2 registers for controlling the Timer, which registers are for the counters, the compare, the interrupts status, etc.

Remember, the options to see the registers in a list is the index, the register map or the bookmarks on the PDF. If none are available you will have a harder time finding the register you need but once found the info should be there.

But a register has 32 bits, what should you put there? And if it's to read, what should you be looking for after a read?

Let's see the "16.4.1 TIM1 control register 1 (TIM1_CR1)". In the case of the timers the registers never have useful bits after the 16th (bit 15) so they don't show the 16 most significant ones on the document (if you check the register map you will see this better)

For those that never really seen a register description, you see here each bit of the register (again just 16 because the upper 16 bits are unused). You can see that there are not only individual bits that configure something but also bit-fields (2 or more bits) that do that too.

For example the bit0, the bit CEN what does it do? Scrolling down you will see, normally the list is from the most significant to the least so bit0 is on the bottom.

Since it's just a bit there are only 2 options. "1" or "0". As you can see a "0" means that the counter is disabled, "1" enables the counter. Like you can see there can be a handy note for some function of the peripheral and how that bit/bit-field can be relevant. This is pretty much what you can expect in any register description!

Let's see now a bit-field, say CKD - bits 9:8.

Now there's more than 2 configurations. It's 2 bits so there's 4 possible configurations. Each means a different division on the timer clock. You can see it's what it does easily by reading the description.

But wait! If you read carefully you will see that "11" is no an option, and it advises you to not program that value.

Actually reserved values are advised to not be programmed as well reserved bits are advised to be kept at default values!

Hence why it's normal to use bit-wise operations like "TIM1_CR1|= xxx" (this is not a macro to program) to avoid changing reserved bits values. Normally there's no problem, either the value you are trying to assign does not affect reserved bits (they are always the most significant bits so that helps) or there's literally not effect, though I would comply with manufacturer's advises.

Now read values? Notice that when looking at the bits of TIM1_CR1 bellow it says "rw". This means the bit can both be read and written to.

There can be read only bits and write only bits ("r" or "w")

You can in the TIM1_CR1 read the current configuration - imagine you don't remember which clock division you used or you simply want a code that uses that to know the timer frequency? You can read the entire registers into a variable "uint32_t value = TIM1_CR1" (again TIM1_CR1 is not the macro to use). Remember that this reads the entire registers so make sure all bits can be read - usually only a entire register will be read-only, not just 1 individual bit (or just some of them) so you should not have much problems checking that. Then just extract the bit-field you want, for the clock division.

I hope this will help anyone in need to understand better the register and how to read the datasheets.

Again, I discourage using only direct register programming but it's important to know how all that works.

Until the next Tutorial!