# Create an Armv8-A embedded application

## In this learning path

- [Introduction](https://learn.arm.com/learning-paths/embedded-and-microcontrollers/bare-metal/)
- [Create and build a Hello World example project](https://learn.arm.com/learning-paths/embedded-and-microcontrollers/bare-metal/hello/)
- [Write a reset handler](https://learn.arm.com/learning-paths/embedded-and-microcontrollers/bare-metal/reset/)
- [Modify the example to use the UART for printf output](https://learn.arm.com/learning-paths/embedded-and-microcontrollers/bare-metal/retarget/)
- [Create event-driven application (1)](https://learn.arm.com/learning-paths/embedded-and-microcontrollers/bare-metal/event-driven1/)
- [Create event-driven application (2)](https://learn.arm.com/learning-paths/embedded-and-microcontrollers/bare-metal/event-driven2/)
- [Switching Exception Levels](https://learn.arm.com/learning-paths/embedded-and-microcontrollers/bare-metal/exception-levels/)
- [Next Steps](https://learn.arm.com/learning-paths/embedded-and-microcontrollers/bare-metal/_next-steps/)

## About this Learning Path

| Skill level:       | Introductory      |
|--------------------|-------------------|
| Reading time:      | 1 hr              |
| Last updated:      | 08 Jul 2026       |

| Author:            | Ronan Synnott, Arm [LinkedIn](https://linkedin.com/in/ronansynnott) |
|--------------------|-------------------|
| Arm IP:            | [Cortex-A](https://support.arm.com/?tab=compute-ip&Product%20Type=Application%20Processors) |
| Tags:              | [Performance and Architecture](https://learn.arm.com/tag/performance-and-architecture), [Baremetal](https://learn.arm.com/tag/baremetal), [Arm Development Studio](https://learn.arm.com/tag/arm-development-studio), [Arm Compiler for Embedded](https://learn.arm.com/tag/arm-compiler-for-embedded), [Arm Fast Models](https://learn.arm.com/tag/arm-fast-models) |

### Who is this for?

This is an introductory topic for embedded software developers new to Armv8-A processors and/or the Arm Compiler for Embedded.

### What will you learn?

Upon completion of this Learning Path, you will be able to:

- Create and build an example project
- Run example on Fixed Virtual Platform (FVP)
- Understand basic boot code and other syntax
- Extend example to use different I/O mechanisms
- Extend example to implement basic exception handling

### Prerequisites

Before starting, you will need the following:

- Some familiarity with embedded programming is assumed

### Summary

You’ll create a bare‑metal Armv8‑A application, build it with Arm Compiler for Embedded, and run it on the `FVP_Base_AEMvA` model. After bringing up a Hello World example that uses semihosting for `printf`, you’ll replace that mechanism by retargeting output to the PL011 UART provided by the Fixed Virtual Platform. You’ll add a minimal EL3 reset handler to boot only one processor and place the remaining cores into sleep. Then, you’ll introduce basic exception handling by routing exceptions to EL3 and configuring the Generic Interrupt Controller (GICv3) with a timer as an interrupt source, enabling a simple event‑driven workflow that you can observe on the model.

### Frequently asked questions

<details>
<summary>Which Arm tools should I install to follow the steps?</summary>
You can use Arm Development Studio with a configured license, or install Arm Compiler for Embedded and Arm Fixed Virtual Platforms (FVP) individually. The examples run on an FVP model.
</details>

<details>
<summary>Which Fixed Virtual Platform should I use, and how many CPUs does it provide?</summary>
Use the FVP_Base_AEMvA Architecture Envelope Model. It’s a generic Arm Architecture platform that implements four processors.
</details>

<details>
<summary>How do I confirm that printf isn't using semihosting before switching to the UART?</summary>
Import `symbol __use_no_semihosting` in `hello.c`. If your build or run depends on semihosting, this exposes the dependency and prompts you to retarget `printf` to the PL011 UART on the FVP.
</details>

<details>
<summary>What should I expect after adding the reset handler?</summary>
The minimal reset handler puts all but one processor to sleep and runs the application on a single processor. This ensures the rest of the example executes on one core.
</details>

<details>
<summary>How do I know my interrupt setup is working?</summary>
Exceptions are routed to EL3 and GICv3 is initialized with the timer as an interrupt source. When the timer triggers, your handler is invoked, demonstrating the event‑driven flow.
</details>
