# [Breaking down the application](https://learn.arm.com/learning-paths/embedded-and-microcontrollers/trustzone_nxp_lpc/trustzone_concepts/)

## In this learning path

- [Introduction](https://learn.arm.com/learning-paths/embedded-and-microcontrollers/trustzone_nxp_lpc/)
- [Run TrustZone Hello World example](https://learn.arm.com/learning-paths/embedded-and-microcontrollers/trustzone_nxp_lpc/hello/)
- [Breaking down the application](https://learn.arm.com/learning-paths/embedded-and-microcontrollers/trustzone_nxp_lpc/trustzone_concepts/)
- [Next Steps](https://learn.arm.com/learning-paths/embedded-and-microcontrollers/trustzone_nxp_lpc/_next-steps/)

In this section, the application is broken down to understand some basic concepts of TrustZone which include:

- Switching security states
- Calling secure functions from the non-secure world

## Switching security states

Start another debug session with the application. This time, instead of hitting “Run” and viewing the complete output you will walk through some key TrustZone concepts used in this application.  
At the start of execution, the program counter is at the start of `main()` in `hello_world_s.c`. The secure mode copy of the startup code has already been executed right at reset time.

In the `main()` function, board hardware initialization is performed followed by the first 2 `printf` statements you saw in the console output:

```c
__output__ PRINTF("Hello from secure world!\r\n");
__output__ PRINTF("Entering normal world.\r\n");
```

The Cortex-M33 processor on the NXP board is running in secure mode up to this point. After these prints, the `TZM_JumpToNormalWorld(NON_SECURE_START)` function is called which initiates the switch to the non-secure world. This function is defined in the `tzm_api.c` source file. This function sets up the non-secure main stack and vector table and gets a pointer to the non-secure reset handler with `__attribute__((cmse_nonsecure_call))`. This key attribute directs the compiler (Arm compiler for embedded in this example) to generate a `BLXNS` instruction. This instruction causes the processor to switch from secure to non-secure world.

## Call a secure function from non-secure world

Now that the processor has switched to non-secure mode it will not be able to access memory and peripherals of the secure world. The processor now executes the non-secure copy of the startup code and reaches the `main()` function of the `hello_world_ns.c` source file.

Here again there are two key print statements which you previously saw in the output:

```c
__output__ PRINTF_NSE("Welcome in normal world!\r\n");
__output__ PRINTF_NSE("This is a test printed from the normal world!\r\n");
```

`PRINTF_NSE()` function is defined with `__attribute__((cmse_nonsecure_entry))`. This attribute is used to call the `PRINTF()` function, which is defined in secure mode. Using this attribute, a secure function can be called from the non-secure world. The function executes an `SG` instruction which is a Secure Gateway instruction. Non-secure code can only call a secure function if the first instruction is a Secure Gateway instruction and it is in a non-secure callable memory region. If these rules are not followed during execution then it results in a security violation.

You have now summarized some important attributes and instructions used while building TrustZone applications all using the simple hello world example on the NXP LPCXpresso55S69 board.
