# Zephyr Architecture guide
## [Hardware porting guide](https://docs.zephyrproject.org/latest/hardware/porting/arch.html)
According to the guide there are certain required and some optional steps inorder for the kernel to boot properly. These steps are Architecture specific and follow and certain order.
First step is the **Early boot sequence**. This involves the different steps that must be taken when a CPU comes out of reset, see the core folder ***arch/arm64/core/***.
Second step is the **Interrupt and exception handling**. Also architecture dependent. see arm ***Arm developer guide*** aswell as ***core/vector_table.S***.
**Thread context switching**
> Zephyr Context switch is dependent on the ABI and each ISA has a different set
**Device drivers**: most drivers are optional, however system clock timer and interrupt controller are often architecture specific and therefor needed.
**Utility libraries:** some kernel APIs rely on architecture-specific implementations.
**CPU idling / power management** architecture specific instructions for putting cpu to sleep, not required but most likely wanted.
## Early boot sequence
The early boot sequence is architecture specific, however the goal of the sequence is similar for all architectures and consists of **5** steps.
1. Setup initial stack
2. If running **XIP kernel** copy initalized data from ROM to RAM
3. if not using ELF loader, zero the BSS section
4. jump to _Cstart() which is responsible for context switching out of fake context running at startup into the main thread.
## Interrupt and exception handling
Devices raises interrupts when needed. Threads raises exceptions when doing operations that is not handled by the serial flow of software itself. Both interrupts and exceptions, pass control to a handler. The handler is known as an ISR in case of interrupts, which is device specific. In case of an exception, the core kernel provides the handler.
Before handling the exception or interrupt the kernel has to:
1. Save the currently running context
2. Detach from sleep mode (wake up devices)
3. Updating the kernel uptime, if getting out of tickless mode.
Ones the handler is finished the kernel has to:
1. Decide wheter or not to perform a context switch.
2. In case of context switch, restore the context being context switched in.
The way this is handled is architecture specific, but the concepts remain the same across most architectures. The architecture specific things include
1. The registers to save and restore
2. The Instructions needed to perform the work
3. The numbering of the exceptions
4. other things
The article suggests looking into ***_IntExit()*** and ***_isr_wrapper()*** for ARM.
Each architecture also implement primitives for
- Locking interrupts irq_lock(), irq_unlock()
- Registering interrupts IRQ_CONNECT()
- Set priority irq_priority_set()
- enabling/disabling interrupts irq_enable(), irq_disable()
The vector table should contain handlers for all interrupts and exceptions that can occur see ***core/vector_table.S***.
## Thread context switching
The main purpose of an RTOS is to support multi-threading. Zephyr supports two types of threads, preemtible and cooperative. Cooperative threads run at a higher priority than preemtible ones, and always preempts them. In case of an interrupt happening within the running of a cooperative thread, the kernel always goes back to running that thread.
The reasons for context switching are:
- If a thread executes a blocking operation, such as taking a semaphore that is not available.
- When a preemptible thread unblocks a thread of higher priority by releasing the object on which it was blocked.
- When an interrupt unblocks a thread of higher priority than the one currently executing. If the currently executing thread is preemptible.
- When a thread runs to completion
- When a thread causes a fatal exception and is removed from the running threads. For example, referencing invalid memory
It is therefore necessary that context switching is able to handle all those cases. The Zephyr kernel keeps the next thread to run in a cache, and thus the context switching code only has to fetch from the cace to select which thread to run.
The two types of context switches are, cooperative and preemptive.
- Cooperative: Running thread wilfully gives control to another thread
- Thread explicitly yields
- Thread tries go gain access to a currently unavailable object and is willing to wait.
- Preemptive: if an ISR (or thread) causes an operation that schedules a higher priority thread and the currently runnin thread is preemtible.
## Thread creation and termination
### Creation
Basically ***_new_thread*** is architecture specific, and should wrappen in ***_thread_entry***.
### Termination
implement architecture specific ***k_thread_abort()*** and set Kconfig option ***CONFIG_ARCH_HAS_THREAD_ABORT*** They refer too ***arch/arm/core/aarch32/cortex_m/kconfig***
## Thread Local Storage
## Device Drivers
The only two mandatory device drivers for a system to function properly is the interrupt controller aswell as a system clock. The rest is not mandatory but rather application specific.
They do however recommend using a console over serial line to enable printk and printf output, but one could configure to use the RAM console instead by appending the ***CONFIG_RAM_CONSOLE*** kconfig option.
## Utility Libraries
two things are mandatory
- Atomic operators
- If instructions do not exist for a given architecture, a generic version that wraps ***irq_lock()*** and ***irq_unlock()*** exosts.
- Find-LSB-set and find-MSB-set
- If instructions do not exist, it is possible to implement the functions as generic C functions.
## CPU idling/power mgmt
## Memory Management