Core 1 Program Counter Misdirection to 0xFEBAF5E8
The issue at hand involves the failure of Core 1 to execute its designated code when booting from QSPI flash on an Intel Cyclone V SoC with an ARM Cortex-A9 dual-core processor. While Core 0 operates as expected, Core 1’s program counter (PC) incorrectly jumps to the address 0xFEBAF5E8 instead of its specified entry point at 0x9FFF0. This behavior suggests a misconfiguration or synchronization issue during the boot process, particularly in the handoff between Core 0 and Core 1. The problem is exacerbated when running in bare-metal mode, where the absence of an operating system increases the complexity of managing core initialization and execution.
The Cortex-A9 processor employs a sophisticated boot mechanism that involves reset vectors, exception handling, and core synchronization. Core 0 typically acts as the primary core, initializing the system and releasing Core 1 from reset. Core 1 then begins execution at its designated entry point. However, the observed behavior indicates that Core 1 is not receiving the correct start address or is encountering an exception that redirects its execution flow. The address 0xFEBAF5E8 is not part of the expected memory map, suggesting a potential issue with the reset vector configuration, memory mapping, or cache coherency.
Incorrect Reset Vector Configuration and Cache Coherency Issues
The root cause of Core 1’s misdirected program counter can be attributed to several factors, including incorrect reset vector configuration, cache coherency issues, and improper memory mapping. The reset vector for Core 1 is set to 0x100000 in Core 0’s firmware, but the linker script for Core 1 specifies an entry point at 0x9FFF0. This discrepancy can lead to undefined behavior, as Core 1 may not be correctly initialized with the intended start address. Additionally, the absence of explicit cache management instructions in the firmware can result in cache coherency issues, particularly when Core 0 modifies memory regions that Core 1 relies upon.
The Cortex-A9 processor utilizes a multi-level cache hierarchy, including L1 and L2 caches, which must be properly managed to ensure data consistency between cores. If Core 0 writes to a memory location that is cached by Core 1, the changes may not be immediately visible to Core 1 due to cache incoherency. This can cause Core 1 to execute stale instructions or access incorrect data, leading to unexpected behavior such as the observed jump to 0xFEBAF5E8. Furthermore, the QSPI flash interface introduces additional complexity, as the bootloader must correctly configure the memory controller and ensure that the flash contents are accurately mapped to the processor’s address space.
Resetting Core 1 with Correct Entry Point and Ensuring Cache Coherency
To resolve the issue, the following steps should be taken to ensure that Core 1 is correctly initialized and that cache coherency is maintained throughout the boot process:
-
Correct Reset Vector Configuration: Modify Core 0’s firmware to set Core 1’s reset vector to the correct entry point specified in Core 1’s linker script. This involves updating the address written to the reset manager register (RSTMGR_CPU1_ADDR) to match Core 1’s entry point of 0x9FFF0. This ensures that Core 1 begins execution at the intended location.
-
Cache Management: Implement cache management routines in both Core 0 and Core 1’s firmware to ensure cache coherency. This includes invalidating the instruction cache (I-cache) and data cache (D-cache) before Core 1 begins execution. Use the
alt_cache_*
functions provided by the HAL to perform cache operations. For example,alt_cache_l1_instruction_cache_invalidate_all()
andalt_cache_l1_data_cache_invalidate_all()
should be called in Core 1’s initialization code to ensure that it fetches the latest instructions from memory. -
Memory Barrier Instructions: Insert memory barrier instructions to enforce the correct ordering of memory operations. Use the
DSB
(Data Synchronization Barrier) andISB
(Instruction Synchronization Barrier) instructions to ensure that all previous memory accesses are completed before proceeding. This is particularly important when modifying memory regions that are shared between cores. -
QSPI Flash Configuration: Verify that the QSPI flash is correctly configured and that the memory controller is properly initialized. Ensure that the flash contents are accurately mapped to the processor’s address space and that the bootloader correctly loads the firmware images for both cores. Use the
alt_mem_*
functions to configure the memory controller and verify the memory map. -
Debugging and Verification: Use JTAG debugging to verify that Core 1’s reset vector is correctly set and that it begins execution at the intended entry point. Monitor the program counter and memory accesses to identify any discrepancies. Additionally, use hardware breakpoints and watchpoints to trace the execution flow and detect any unexpected jumps or exceptions.
By following these steps, the issue of Core 1’s misdirected program counter can be resolved, ensuring that both cores execute their designated code correctly when booting from QSPI flash. Proper reset vector configuration, cache management, and memory barrier usage are critical to achieving reliable operation in a dual-core ARM Cortex-A9 system.