4.07 Row-Major Memory Contiguity, Nested Loops & Direct Memory Access (DMA)
💻 1. Annotated Source Code
#include <iostream> using namespace std; int main() { int myNums[2][3] = { {1, 2, 3}, {4, 5, 6} }; cout << myNums[0][2] << endl; myNums[1][0] = 14; cout << myNums[1][0] << endl; //for (int row = 0; row < 2; row++) { // for (int col = 0; col < 3; col++) { // cout << myNums[row][col] << " "; // }//end inner for // cout << endl; //}//end outer for for (int row = 1; row >= 0; row--) { for (int col = 2; col >= 0; col--) { cout << myNums[row][col] << " "; } cout << endl; } return 0; }
📐 2. Architecture & UML Class Model
📚 3. Core C++ Concepts Deep-Dive
1. Row-Major Contiguous Memory Layout
In C and C++, multidimensional arrays are laid out in row-major order: the second index changes fastest. In memory, grid[2][3] is stored as a single contiguous 1D block of 6 elements.
2. Address Calculation Formula
The memory address of element grid[row][col] is calculated as:
$$\text{Address} = \text{Base} + ((\text{row} \times \text{COLS}) + \text{col}) \times \text{sizeof}(T)$$
⚡ 4. Embedded Systems & Hardware Reality
1. Cache Line Thrashing from Column-Major Access
Iterating column-first (grid[col][row]) strides through memory by COLS * sizeof(T) bytes on every step. This causes a cache miss on every single access. Always iterate row-first!
2. Direct Memory Access (DMA) Framebuffers
Because 2D arrays are contiguous in SRAM, a microcontroller DMA controller (e.g. STM32 DMA2D / Chrom-ART) can stream full display frames directly from SRAM to an SPI/I2C TFT display with 0% CPU utilization.
💡 5. Production-Ready Embedded Refactoring
Type-safe flat 2D display framebuffer wrapper with DMA compatibility:
#include <cstdint> #include <array> template <size_t Rows, size_t Cols> class Framebuffer2D { private: // Contiguous in memory; 100% DMA transfer compatible std::array<uint16_t, Rows * Cols> pixels_{}; public: constexpr void set_pixel(size_t r, size_t c, uint16_t rgb565) noexcept { if (r < Rows && c < Cols) { pixels_[r * Cols + c] = rgb565; } } const uint16_t* dma_buffer() const noexcept { return pixels_.data(); } constexpr size_t byte_size() const noexcept { return pixels_.size() * sizeof(uint16_t); } };
📝 Knowledge Verification Quiz
Test your understanding of the C++ concepts and embedded microcontroller trade-offs covered in this guide. Click any option for instant feedback.