nuttx/Documentation/guides/chip-specific/stm32nullpointer.rst
Vinicius May f6ecf80ebb Documentation: brand new layout for NuttX documentation.
The documentation grew one page at a time, so the tree follows the
history of who wrote what and not the shape of NuttX. Scheduling is
spread over three places, a driver page can sit above the subsystem
that owns it, and the front page lists everything at the same level.
That is a lot to face when all you want to know is where the scheduler
lives.

This change files every page under the code it describes. It is a move,
not a rewrite: outside the ten pages named below, every page keeps the
text that is already in master, and no page's text is deleted.

What it does:

* Groups the table of contents into nine chapters.
* Moves the OS subsystems under os/: scheduling, memory, drivers,
  filesystem, networking, IPC, interrupts, libs, time.
* Renames the platform pages to the names the source tree uses, and
  derives their tags from the tree instead of by hand.
* Splits guides/ by subject.
* Adds Documentation/redirects.py, with a rule for every page that left
  its old path, so old URLs keep working. The redirect page also carries
  a link's #anchor across to the new page.

Ten pages have text that is new or rewritten. Nine of them are the
landing page of a chapter, which has to exist for the new structure:

    index                  the front page
    os/index               OS Design
    os/scheduling/index    Scheduling
    os/interrupts/index    Interrupts
    os/ipc/index           IPC
    os/time/index          Time and timers
    about/index            About
    developing/index       Developing NuttX
    ReleaseNotes/index     Release notes

The tenth is os/libs/libbuiltin, the only page here with technical
content: libs/libbuiltin/ had no page at all. Five SVG diagrams come
with these pages, hand-written XML with no editor metadata.

Nothing outside Documentation/ is touched.

How it was checked:

* Sphinx builds with -W: no warnings, and no document left outside a
  toctree.
* A script, offered in the PR, proves the narrow claim this rests on.
  For every page outside the ten named above it erases what a move
  touches -- link target, path, tag line, toctree block, table border --
  from the whole old text and the whole new text, and requires the two
  to be byte for byte identical. It also requires every sentence of a
  deleted page to turn up somewhere, and every page that left its old
  path to have a redirect, from a URL that existed, to where its content
  went. It exits non-zero and names the page if any of that is not true,
  and it tests added pages too, so forgetting to declare one cannot make
  it pass.
* An independent audit checked 133 factual claims on these ten pages
  against the tree, one shell command per claim: 130 confirmed, 1
  refuted and fixed here, 2 not checkable.
* tools/checkpatch.sh is clean over the range.

The diff is large because moving a page changes every link that points
to it. Most of it is pure renames, and board pages that gained one tag
line.

Assisted-by: Claude:claude-opus-5
2026-10-08 01:40:54 +08:00

70 lines
3.1 KiB
ReStructuredText

============================
STM32 Null Pointer Detection
============================
The NULL Pointer Problem
========================
A common cause of software bugs is null pointers. Pointers may be NULL if they
are un-initialized and un-checked. The use of NULL pointers almost always results
in something bad happening. Often, NULL pointer access can cause error exceptions
and or diagnostic crashes. But on MCUs that have valid address decoding at address
0x0000:0000, the use of NULL pointers may not cause a crash at all but may, instead,
cause strange behaviors that can sometimes be difficult to debug.
Cortex-M Memory
===============
The Cortex-M family (Cortex-M0, M3, and M4) are such MCUs. They have their
interrupt vectors positioned at address zero. Because of this, NULL pointer
accesses will not necessarily cause crashes. Instead, the NULL pointers will
access memory in the vicinity of the vector table and who knows what will happen
next?
STM32 Memory Aliasing
=====================
The STMicro STM32 family of Cortex-M3/4 MCUs do things a little differently.
FLASH is physically addressed at address 0x0800:0000; the STM32 vector table
is then physically located at 0x0800:0000 instead of 0x0000:0000. If the STM32
hardware is configured to boot from FLASH, then the STM32 will remap the
FLASH memory so that is aliased at address 0x0000:00000. In that way, the STM32
can boot from FLASH or external memory or any other memory region that it is
capable of mapping.
In the NuttX linker scripts, the applications are linked to execute from the
physical FLASH region at address 0x0800:0000. All valid FLASH memory access
will then access memory in the 0x0800:0000 FLASH address range. But illegal
NULL pointer access will access the aliased copy of FLASH beginning at 0x0000:0000.
So we still have the problem.
The Cortex-M Memory Protection Unit
===================================
The Memory Protection Unit (MPU) is an optional component of a Cortex-M implementation.
Most popular Cortex-M3/4 MCUs do support the MPU. The MPU can be used to protect regions
of memory so that if there is any attempted, unauthorized access to certain memory
regions, then a memory protection violation exception will occur and the system will
detect the illegal access.
See the ARM website for more information about the Cortex-M3/4 families and the
Cortex-M3/4 MPU. See, for example
`2.2. Memory Protection Unit (MPU) <http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dai0179b/CHDFDFIG.html>`_.
Using the MPU to Detect Null Pointer Usage
==========================================
So, for the STM32, one thing that we can do is to program the MPU to prohibit software
access to the memory region beginning at address 0x0000:0000. Petteri Aimonen posted a code
snippet on the NuttX Forum showing how to do this. Here is Petteri's post:
.. code-block:: C
/* Catch any null pointer dereferences */
int region = 0;
putreg32(region, MPU_RNR);
putreg32(0, MPU_RBAR);
putreg32(MPU_RASR_ENABLE | MPU_RASR_SIZE_LOG2(20) | (0xFF << MPU_RASR_SRD_SHIFT) | MPU_RASR_AP_NONO, MPU_RASR);
mpu_control(true, false, true);