Skip to content
Home » What’s really going on inside of micro-controllers?

What’s really going on inside of micro-controllers?

Programming electronics has gone from being exclusive to universities and fortune 500 companies to something that any Joe can successfully start doing tonight. A part of the e easing of the learning curve can be attributed to products such as Arduino© and STM’s Nucleo© Hardware abstraction layer (HAL). These programs have laid a lot of ground work for a user to easily code what they want the chip to do in a human readable fashion as shown in the code snippet below for programming one of the Star Boards.

//----------LED Blink----------//

int main(void) 
{
    PA03_OUT; //--- Declares pin 3 is an output

    while(1) //--- infinite loop
    {
        SET_PA03; //--- Sets pin3 to a high state
        fnSimpleDelay(10000); 
        CLR_PA03; //--- Sets pin3 to a low state
        fnSimpleDelay(10000);
    }
}

Thirty seconds of reading that snippet and you can see that it’s a program that turns on and off a pin and what ever the pin is connected to. This abstraction is good for a human to easily read and write code, but it is not what the chip needs in order to perform its tasks. How does the chip know which pin is pin 3? How does it know what it means to set a pin high or low? The answer to that is manipulation of port registers and their associated values.

Every chip that has ever been made with integrated hardware such as timers, GPIOs and converters assigns an address to every register associated with that hardware. Every register can hold an eight to thirty two bit value, and every bit in the value corresponds to a specific setting for the register. Ultimately, everything comes back to “bare metal” programming.

When manipulating a pin in bare metal programming, three things are happening. First you need to define the specific pin you are working with. Most pins are tied to one of several general purpose input and output peripherals which are embedded in the chip and have several registers which you can use to isolate the individual pins. Second define the pin’s function. Each pin can be an input, an output, an analog, or an alternate function which ties to other peripherals such as timers, USARTs, or i2c communication. Finally consider if the pin is going to function need a pull up or pull down push-pull or open drain. Further information on GPIOs will be written in a later article.

If we break down the above code snippet from its source code, you can see that PA03_out corresponds to a macro defined in commonheader

#define PA03_OUT GPIOA_MODER &= 0xFFFFFF3F; GPIOA_MODER |= 0x00000040;

In this macro, GPIOA_MODER is anded so the bits that correspond to pin 3 are set to 00, and then they are ored so they are then set to 01 which will make pin3 of GPIOA act as an output. SET_PA03 and CLR_PA03 also work in a similar way, but they work by manipulating the GPIOA_BSRR register as seen in the code below.

//----------Simple Delay----------//

void fnSimpleDelay(u16 ticker) 
{
    fnTimSixInit();
    TIM6_CR1 |= 0x0008; //--- set one pulse mode
    TIM6_PSC = 7199; //--- adjust the counter speed to 1/10000 second pulse
    TIM6_ARR = ticker;
    TIM6_CR1 |= 0x0001; //--- start the timer

    /*
    loop until the counter counts up to the ARR(ticker) and an update event
    occurs and deactivates the timer setting TIM6_CR1 to 0x0008.
    */
    while(TIM6_CR1 != 0x0008) //--- test to see if timer turns off
    {
        nop2;
    }
}

In fnSimpleDelay, the registers for the timer are written to specific values which setup one pulse to work over a specified time once the CEN bit in CR1 is set to on and setting the CR1 register to equal 0x0009. Once the timer has counted up to the specified value determined in the ARR register, the CEN Bit gets turned back to zero and sets the value to 0x0008 which can be read as a signal to go onto the next step after the delay is over. There is a lot more you can do with timers than just setting delays. More information on timers will be written in a later article.

Human abstracted code is excellent for getting as many people started in embedded programming as possible. It can be more quickly written, and read and easily understood for troubleshooting and development. However, it is important to begin dipping your feet into bare metal programming in order for you the user to get a better and more complete understanding of what is going inside of the chip.

Technology vector created by rawpixel.com – www.freepik.com