ESP32 RISC-V implementation Load/Store misalignment behaviour

rbabaousmail
Posts: 2
Joined: Wed Jun 03, 2026 2:46 pm

ESP32 RISC-V implementation Load/Store misalignment behaviour

Postby rbabaousmail » Wed Jun 03, 2026 3:35 pm

Hi,

I would like to get a clear understanding of how ESP32 RISC-V implementations handle misaligned load/store memory accesses.

The RISC-V specification states that the behavior of misaligned accesses is implementation-specific (The RISC-V Instruction Set Manual, Volume I: Unprivileged Architecture, Section 2.6 "Load and Store Instructions", page 34).

When reviewing the technical reference manuals for various ESP32 RISC-V devices (ESP32-P4, ESP32-C5, ESP32-C6, ESP32-C3, ESP32-C2, etc.), I could not find a clear statement describing how `lw`/`sw` instructions handle misaligned accesses. However, when examining the documented values of the `mcause` register, exceptions with IDs `0x4` (Load address misaligned) and `0x6` (Store/AMO address misaligned) are not listed. This seems to suggest that these exceptions are not generated by the implementation, but instead handled transparently.

The only explicit mention I found is that a Store/AMO address misaligned exception can be generated when `lr.w` or `sc.w` accesses are not properly aligned.

My questions are:
  • How do ESP32 RISC-V implementations handle misaligned memory accesses?
  • Is there any ESP32 RISC-V implementation that does not support misaligned memory accesses and instead generates a misaligned address exception for `lw/`sw` instructions?
  • The ESP-IDF documentation mentions the errors "Load Address Misaligned" and "Store Address Misaligned" https://docs.espressif.com/projects/esp ... misaligned. Can these exceptions actually occur on ESP32 RISC-V devices?
To investigate this, I ran the following test on an ESP32-C3 using ESP-IDF v5.5.3:

Code: Select all

void __attribute__((noreturn)) call_start_cpu0(void)
{
    volatile uint8_t buf[8] = {
        0x01, 0x02, 0x03, 0x04,
        0x05, 0x06, 0x07, 0x08
    };

    uint32_t aligned;
    uint32_t unaligned;

    // Use inline assembly to ensure the compiler does not optimize the accesses away.
    asm volatile("lw %0, 0(%1)" : "=r"(aligned) : "r"(buf));
    asm volatile("lw %0, 0(%1)" : "=r"(unaligned) : "r"(buf + 1));

    ESP_EARLY_LOGE(TAG, "Aligned address: 0x%x", buf);
    ESP_EARLY_LOGE(TAG, "Aligned read: 0x%x", aligned);
    ESP_EARLY_LOGE(TAG, "Unaligned address: 0x%x", (buf + 1));
    ESP_EARLY_LOGE(TAG, "Unaligned read: 0x%x", unaligned);

    while (1) {
        // Test complete.
    }
}
The output was:

Code: Select all

ESP-ROM:esp32c3-api1-20210207
Build:Feb  7 2021
rst:0x7 (TG0WDT_SYS_RST),boot:0xc (SPI_FAST_FLASH_BOOT)
Saved PC:0x403cbfb2
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fcd5710,len:0x168
load:0x403cbf10,len:0xb4
load:0x403ce710,len:0x74
entry 0x403cbf10
E (23) boot: Aligned address: aligned = 0x3fcde538
E (27) boot: Aligned read: *(aligned) = 0x4030201
E (32) boot: Unaligned address: unaligned = 0x3fcde539
E (36) boot: Unaligned read: *(unaligned) = 0x5040302

MicroController
Posts: 2661
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: ESP32 RISC-V implementation Load/Store misalignment behaviour

Postby MicroController » Thu Jun 04, 2026 11:36 pm

Can these exceptions actually occur on ESP32 RISC-V devices?
I imagine they would occur when you attempt a misaligned access on peripheral registers, or RTC RAM.

rbabaousmail
Posts: 2
Joined: Wed Jun 03, 2026 2:46 pm

Re: ESP32 RISC-V implementation Load/Store misalignment behaviour

Postby rbabaousmail » Tue Jun 09, 2026 7:31 am

Thanks for your reply, i have tested the RTC RAM with

Code: Select all

void __attribute__((noreturn)) call_start_cpu0(void)
{
    // SOC_RTC_DRAM_LOW = 0x50000000
    volatile uint8_t *rtc = (volatile uint8_t *)SOC_RTC_DRAM_LOW;
    uint32_t val;

    rtc[0]=0x01; rtc[1]=0x02; rtc[2]=0x03; rtc[3]=0x04;

    asm volatile("lw %0, 0(%1)" : "=r"(val) : "r"(rtc));
    ESP_EARLY_LOGI(TAG, "lw aligned   = 0x%08x", val);

    asm volatile("lw %0, 0(%1)" : "=r"(val) : "r"(rtc + 1));
    ESP_EARLY_LOGI(TAG, "lw misalign1 = 0x%08x", val);

    asm volatile("lw %0, 0(%1)" : "=r"(val) : "r"(rtc + 2));
    ESP_EARLY_LOGI(TAG, "lw misalign2 = 0x%08x", val);

    while (1) {}
}
Output

Code: Select all

I (18) boot: lw aligned   = 0x04030201
I (21) boot: lw misalign1 = 0xa0040302
I (25) boot: lw misalign2 = 0x43a00403
So misaligned accesses to RTC RAM are handled.

MicroController
Posts: 2661
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: ESP32 RISC-V implementation Load/Store misalignment behaviour

Postby MicroController » Wed Jun 10, 2026 8:40 am

Hm, ok.
The C3's TRM in fact does not seem to indicate any alignment restrictions, neither for RAM nor for peripheral registers. From the CPU's perspective, everything is accessed via the same data bus.
Could try out this for peripheral access:

Code: Select all

#include <stdint.h>
#include "soc/systimer_struct.h"

uint32_t test(void) {
 volatile uint32_t* const paligned = &SYSTIMER.unit_val[0].hi.val;
 volatile uint32_t* const p = (volatile uint32_t*)((volatile uint8_t*)paligned + 1);
 return *p;
}

Who is online

Users browsing this forum: ChatGPT-User, Google [Bot], PerplexityBot and 11 guests