
Welcome to the complete Cortex-M embedded developer series; determine if you can skip sections 2 and 3 based on prior Cortex-M experience, and use section 10 for installation guidance.
ARM designs processors with the RISC philosophy, prioritizing simple, single-cycle instructions and pipelines, and relies on compilers; they license architectures to brands such as Apple and Samsung.
Arm processors are designed to be small and power efficient for mobile and embedded devices, emphasizing risk architecture with high code density, endianness options, and conditional execution.
Explore how an arm core and buses coordinate peripherals like real-time clock and usart in embedded devices. See arp arbiter and apb bridge link memory and peripherals.
Explore ARM bus technology and the AMBA bus protocol, distinguishing bus masters and slaves, physical and protocol levels, and how AHB, ASP, and APB enable higher throughput.
Explore the memory hierarchy from cache and main memory to ROM, flash, DRAM, SRAM, and EEPROM, and see how memory width and ARM instruction sets affect performance.
Explore the arm's generic peripheral architecture, including memory-mapped peripherals, base-address offsets, and the roles of the memory and interrupt controllers (standard and vectored).
Compare von Neumann and Harvard architectures, outlining single data bus versus two buses, memory for data and instructions, and their implications for cost and performance.
Explore cache and tightly coupled memory that boost ARM performance and enable deterministic real-time timing, comparing von Neumann unified caches with Harvard's separate caches and TCM near the core.
Explore memory management extensions with the NPU and MMU, outlining regions, access permissions, and translation tables. Compare protected and non-protected memory scenarios in embedded systems.
Explore core processor extensions for arm cortex-m4, including the core processor interface, hardware floating point, and cache memory and management functionality. Learn to access and use these cores in code.
Explore the programmer's model of the arm architecture and data types—8-, 16-, 32-, and 64-bit—alongside the 32-bit arm and 16-bit thumb instruction sets.
Master arm processor modes across arm7tdmi and cortex-m4, including user, privileged, supervisor, abort, and undefined modes, plus irq/fiq interrupts and exception handling.
Explore the Arm7tdmi-s vector table and exception vector table, showing how 0x00000 reset and 0x18 interrupt addresses route to the startup reset handler.
Explore the ARM7TDMI register architecture, including the register bank, general purpose and status registers, and how mode changes swap banked r13, r14, and sp sr.
Explore Cortex-M registers, including 17 general-purpose registers, r0–r12, r13 (stack pointer), r14 (link register), r15 (program counter), the main and process stack pointers, and access PSR via MRS and MSR.
Explore the cortex-m vector table, its exception types and memory addresses, and why the least significant bit is one, noting about ten exceptions and the thumb two instruction set.
Explore how a three-stage pipeline speeds Cortex-M execution by overlapping fetch, decode, and execute, and how filling the pipeline enables one instruction per cycle.
Explore the ARM processor family and architecture revisions, from arm7, arm9, and arm11 to cortex-a, cortex-r, and cortex-m variants, and armv7-a to armv8 with hardware encryption for IoT.
Introduces the cortex-a and cortex-r families, with cortex-a as application processors for smartphones and high-end devices, and cortex-r as real-time processors for safety-constrained applications.
Discover the Cortex-M processor family, from M0 to M7, including M23 and M33, highlighting low-power wearables and high-compute DSP-enabled use cases, plus hardware encryption for IoT security.
Explore the ARM Cortex-M overview, highlighting 32-bit cores, memory addressing by bit size, ARM's licensing of processor designs and architectural specifications, including instruction sets.
Understand how 32-bit registers, data paths, and bus interfaces define cortex M. See how the arithmetic logic unit and the control unit enable 4.2 gigabytes of memory addressing.
Explore the cortex-m family of 32-bit processors, including m0, m0+, m1, m3, m4, and m7; compare code density, energy efficiency, and interrupts up to 240 with priority options.
Distinguish microprocessors from microcontrollers by noting that a microprocessor offers a CPU only, while a microcontroller includes CPU, RAM, ROM, and internal peripherals.
Explain the Cortex-M architecture and Harvard architecture with separate data and instruction buses, then illustrate load-store operation moving operands from memory to registers and back.
Explore the cortex-m register bank of 16 registers, including 13 general purpose (R0–R12) with R13, R14, and R15 roles, plus PSR and the interrupt registers primask, faultmask, and basePRI.
Explore how the 32-bit program status register (psr) combines apsr, ipsr, and epsr into one with overlapping and reserved bits. See how bit ranges map to each subregister.
In this lesson, we shall take a deep look into how computers count.
Explore the debug view, customize locals and memory panels, and compare disassembly, machine code, opcodes, and mnemonics with memory addresses as the processor stops at the main function.
Explore the memory view and disassembly view, verify that each address stores the same instruction, and display instructions in 16-bit blocks using a signed short.
Step through the code to see how the local counter initializes to zero and is moved into R1, while the PC and registers update with each instruction.
Explore counting in a bare-metal ARM Cortex-M program by applying increment and decrement to a counter, then loop to observe repeated counting.
Observe how the compiler handles conditions through a while loop, tracking the counter and branching in the disassembly using CMP, BLT, and the N, Z, C and V bits.
Demonstrate how the program counter (PC) stores the next instruction address and is modified by branches, enabling an eight-count loop that resets with an if statement.
Explore the Cortex-M memory map and locate where memory and peripherals reside, using the datasheet and memory map table to identify flash, ROM, and peripheral addresses.
Explore the Cortex-M memory map: 256k flash at 0x00000000-0x0003ffff, 32k sram at 0x20000000-0x20007fff, io at 0x40000000-0x4000ffff, and private peripheral space at 0xe0000000-0xe000ffff, then verify in the debugger memory view.
Explain endianness by contrasting big-endian and little-endian memory layouts, showing how 16-bit and 32-bit values occupy bytes and addresses, including MSB and LSB placement.
In this lesson we look at what actually makes a variable a global one
Learn the arm cortex-m instruction set architecture, including thumb-2 16-bit and 32-bit instructions, to balance code density and performance before writing in C or C++.
Explore upward compatibility across the cortex-m family, showing how code compiled for M0/M0+ and M1 can run on M3, M4, and M7, while noting downward compatibility is not guaranteed.
Learn assembly syntax by identifying the four instruction fields: label field, opcode, operand, and optional comment, and explore directives or pseudo ops that guide assembly and program behavior.
Learn 14 assembly directives for cortex-m programming, including thumb, code, area, line, export, import, end, dcb, dcw, dcd, etu, and dot text, to organize sections and enable C calls.
Explore the Texas Instruments TM4C123 launchpad, a cortex-m4 microcontroller with 256 kb flash, 32 kb RAM, and 80 MHz, featuring a debugger, USB ports, two inputs, and rgb led.
Use board datasheets and the C launchpad guide as references, then implement a first assembly program to keep the red led on, exploring reset handlers and startup files.
Explore the seven opcodes used in the first program: move, ldr, store, b, bl, bx lr, and nop, covering memory access, immediate values, and low vs high register constraints.
Inspect the source code of the first program, the red one, and explain two directives, initialization, the loop, and how the initialization returns a value and turns on the light.
Create your first project in uvision by selecting the tm4c123 device and adding startup.c and startup.s. Set the target to 16 MHz and attach the stellaris icd driver for debugging.
Create and save a new assembly file with the .s extension, add it to the TM4C123 project, and enable PF1 to drive the red LED via resistors.
Initialize a gpio pin for an led on tm4c123 by enabling port clock, setting the pin as output in the direction register, enabling digital, and writing to the data register.
Write and export a bare-metal ARM Cortex-M program for TM4C123, initialize GPIO F, enable Port F clock, and turn on the red LED at pin 1 using LDR and OR.
Explore logical operations, or, and, and exclusive or, with inputs and outputs, enable ports, and access gpio registers, while using symbolic header files and addresses to simplify cortex-m programming.
Create an infinite loop subroutine light_on by looping back to a label, turning the red led on and off via the gpio port f data register, with reset and main.
Expand project two by mastering new opcodes, including CMP and BNE/BEQ, to drive a switch-activated led and implement delay subroutines with subs updating PSR flags.
Extend the code to include switch inputs with pull up, unlock and commit port F pins, and drive the red led on PF1.
Complete project two part two by implementing a loop with a countdown delay, reading a pull-up gpio input, and driving a red LED or motor.
Configure PF2 as an output and enable its digital function, then verify the blue led lights up; plan to enable green and add a second switch to mix colors.
Enable the green led by configuring gpio pins as outputs in the gpio init subroutine, set digital enable, and experiment with color control using switches and potential hardware enhancements.
Enable a two-switch input-driven color output on the tm4c123 by comparing r0 to 0x10, branching to switch two on, and using subroutines to show green, blue, or red.
Learn to call assembly code from a C source on Cortex-M, export the function, and prototype it in C to return values in R0 for performance.
Discover how to write a function in C and import it into assembly for the TM4C123, enabling peripherals, returning results in R0, and blending C with assembly.
We declare data area and a 32-bit variable amount, export it, implement amount_func to assign 89, then call from C and read the value to verify.
Explore the complete list of cortex m assembly instructions on the cortex m.com website, organized into arithmetic, logical, branch, memory access, and interrupt instructions with explanatory comments.
Declare a pointer to an integer, store the counter's address in it, and dereference it to read or modify the counter, noting shortened machine code in the disassembly view.
Experiment with a pointer to drop a value into a memory address, using an unsigned integer address, typecasting, and a pointer variable to access and store data.
Blink the red, green, and blue leds by enabling port F clock, setting pins as outputs, and writing to gpiodata via the APB memory map using addresses and offsets.
Point an unsigned pointer to tm4c123, wake up port f, set pins 1-3 as outputs, and drive red, green, and blue LEDs by writing 0x2, 0x4, 0x8 to data register.
Blink LEDs on the tm4c123 cortex-m bare-metal setup by writing to the data register via a pointer, using a countdown delay and a while loop to toggle pins.
define memory addresses as named registers with pre-processors to improve readability, using #define and braces for o'clock, direction, enable, and data registers.
Consult the data sheet to map registers to their official names, replace code identifiers with GPIOF_DIR, GPIOF_DEN, and GPIOF_DATA. Observe LEDs blink at the same rate, confirming the code works.
Use vendor supplied tm4c header files to access registers by name, avoiding manual renaming; include tm4c123gh6pm.h in your project to map GPIO data, direction, and digital enable registers.
Clarify the volatile keyword's role, its difference from unsigned int vs uint32_t, and how it prevents compiler optimizations on gpio registers in Cortex-M microcontrollers.
Use the volatile keyword to prevent optimization across different compilers and optimization level settings, ensuring variables like int delay remain persistent and behave securely in bare-metal programming.
Learn bitwise operations to modify specific bits in registers without disturbing others. Explore the six bitwise operations—and, or, xor, not, right shift, and left shift—in embedded C.
Use bitwise operations to turn on red, blue, and green LEDs by shifting bits, and improve readability with defines for colors in cortex-m assembly.
Learn to use bitwise operations to control GPIO port F LEDs, enabling and preserving specific bits with or, not, and operators, and improve readability with concise expressions.
Learn to write your own functions to avoid repetition, declare a delay function with void return type and prototype, place it outside main, and call it for the delay loop.
Explore function arguments by modifying a blink rate for leds using a local integer time variable, adjusting upper limits and calling the function to observe different timings.
Import functions across files by modularizing code into delay.c and delay.h, then include prototypes in the main file to enable testing and consistent behavior on the board.
Guard the delay function with an include guard using ifndef to prevent multiple definitions. Define it once and include it safely with other headers to ensure robust, efficient compilation.
Explains declaring fixed width integer types using stdint.h under the c99 standard. Shows int8_t to int32_t and uses sizeof to verify sizes for consistent memory across processors.
define and use C structures by declaring with struct and a name, add age and height fields (uint8_t), create instances, and explore anonymous declarations and typedef to simplify usage.
Learn how typedef creates a synonym for built-in or user-defined types to clarify structure declarations and simplify code in embedded systems, following MISRA C 2012.
Access structure members with the dot operator to read and set fields like age and height, and apply it to simple computations in code.
Welcome to the Complete ARM Cortex-M Bare-Metal Programming (TM4C123) course.
This course assumes no prior knowledge of either cortex-m or embedded-c programming.
All it requires from students is curiosity.The course takes a practical approach to cover key areas such as pointers ,structures, memory navigation and the Cortex-M Software Interface Standard. The main aim of this course is to provide learners with practical skills and a strong foundation that they can build upon to start producing well written code which runs efficiently and leverages the key aspects of the ARM Cortex-M ecosystem. This course has many key sections.
The goal of the assembly peripheral section is to teach you how to navigate the microntroller reference manual and datasheet to extract the right information to professionally build peripheral drivers and firmware. To achieve this goal, no libraries are used in this course, purely ARM Assembly Language and bare-metal embedded C
By the end of this section you will be able configure microcontroller peripherals like ADC, UART, GPIO, TIMER etc in assembly. You will also master the ARM architecture, ARM Instruction Set Architecture (ISA) and building professional embedded firmware in assembly for ARM processors.
Please take a look at the full course curriculum.
REMEMBER : I have no doubt you will love this course. Also it comes with a FULL money back guarantee for 30 days! So put simply, you really have nothing to loose and everything to gain.
Sign up and lets start toggling some register bits.