> ## Documentation Index
> Fetch the complete documentation index at: https://launchpad.anxlabs.com/llms.txt
> Use this file to discover all available pages before exploring further.

# ANX SDK Initialization and System Functions

> Initialize the ANX SDK, access system information, manage device reboots, and use logging and delay utilities provided by anx/anx.h.

`anx/anx.h` is the core header you include in every ANX application. It initializes the ANX OS integration layer — setting up the task scheduler, memory allocator, and peripheral clocks — and provides the system utilities your application needs from the very first line of `app_main()` all the way through to graceful shutdown and reboot.

## `app_main()` Entry Point

Define `void app_main(void)` as the single entry point for your application. ANX OS calls this function automatically after the system initializes all hardware and loads `config.json` from the device filesystem. You do not need a `main()` function — the ANX OS boot sequence handles everything before `app_main()` is invoked, so all peripherals are ready the moment your code runs.

```c app_structure.c theme={null}
#include "anx/anx.h"

void app_main(void) {
    // Called by ANX OS after boot
    // All peripherals are ready at this point
    ANX_LOGI("APP", "Application started");
    ANX_LOGI("APP", "Firmware: %s", anx_firmware_version());
    ANX_LOGI("APP", "SDK: %s", anx_sdk_version());
}
```

<Note>
  ANX OS will halt with a fatal error if `app_main()` is not defined in your application binary. Make sure it is present in exactly one translation unit.
</Note>

## System Information Functions

Use these functions to read device metadata at runtime. They are safe to call anywhere inside `app_main()` and are commonly used in startup log messages or OTA compatibility checks.

### `anx_firmware_version()`

Returns a null-terminated string containing the firmware version currently running on the device (for example, `"1.2.0"`).

<ResponseField name="return" type="const char *">
  A pointer to a static string holding the firmware version in `MAJOR.MINOR.PATCH` format. Do not free or modify this string.
</ResponseField>

***

### `anx_sdk_version()`

Returns a null-terminated string containing the version of the ANX SDK your application was compiled against (for example, `"1.2.0"`).

<ResponseField name="return" type="const char *">
  A pointer to a static string holding the SDK version in `MAJOR.MINOR.PATCH` format. Do not free or modify this string.
</ResponseField>

***

### `anx_device_id()`

Returns a null-terminated string containing the unique device identifier derived from the module's 48-bit MAC address (for example, `"a1b2c3d4e5f6"`). Use this value to uniquely identify a device in your backend or MQTT topic hierarchy.

<ResponseField name="return" type="const char *">
  A pointer to a static string holding the 12-character hexadecimal device ID. Do not free or modify this string.
</ResponseField>

***

## Logging Functions

ANX OS provides four log-level macros that write formatted output to the serial console. Each macro accepts a short **tag** string (conventionally the subsystem name, like `"APP"` or `"WIFI"`) so you can filter output from multiple components at a glance.

| Macro                     | Level   | Visibility                                                       |
| ------------------------- | ------- | ---------------------------------------------------------------- |
| `ANX_LOGE(tag, fmt, ...)` | Error   | Always shown                                                     |
| `ANX_LOGW(tag, fmt, ...)` | Warning | Always shown                                                     |
| `ANX_LOGI(tag, fmt, ...)` | Info    | Shown at `info` log level and above                              |
| `ANX_LOGD(tag, fmt, ...)` | Debug   | Shown only when `log_level` is set to `"debug"` in `config.json` |

```c logging_example.c theme={null}
#include "anx/anx.h"

void app_main(void) {
    ANX_LOGI("APP", "Device ID: %s", anx_device_id());
    ANX_LOGD("APP", "Debug details visible only in debug builds");
    ANX_LOGW("APP", "Low memory: %u bytes free", anx_free_heap());
    ANX_LOGE("APP", "Critical failure, rebooting");
    anx_reboot();
}
```

<Tip>
  Keep tag strings short — four to six characters — so log lines stay readable at a glance in a serial monitor.
</Tip>

## Delay and Timing Functions

### `anx_delay_ms()`

Yields the CPU for the specified number of milliseconds, allowing other tasks in the ANX OS scheduler to run during the wait.

<ParamField path="ms" type="uint32_t" required>
  Number of milliseconds to delay. The actual delay may be slightly longer than requested due to scheduler tick resolution.
</ParamField>

<ResponseField name="return" type="void">
  This function does not return a value.
</ResponseField>

***

### `anx_delay_us()`

Busy-waits for the specified number of microseconds, blocking the CPU for the entire duration. Use this only when you need sub-millisecond precision that the scheduler cannot guarantee.

<ParamField path="us" type="uint32_t" required>
  Number of microseconds to busy-wait. Avoid values larger than a few hundred microseconds in tasks that share CPU time with networking or file I/O.
</ParamField>

<ResponseField name="return" type="void">
  This function does not return a value.
</ResponseField>

<Warning>
  `anx_delay_us()` blocks the CPU for its entire duration. Calling it with large values in a networking-heavy application can cause Wi-Fi stack timeouts or dropped MQTT connections.
</Warning>

***

### `anx_uptime_ms()`

Returns the number of milliseconds elapsed since the last system boot. Use this for elapsed-time measurements and timeouts without depending on wall-clock time.

<ResponseField name="return" type="uint64_t">
  Milliseconds since last boot. This value wraps after approximately 584 million years of continuous uptime.
</ResponseField>

```c timing_example.c theme={null}
#include "anx/anx.h"

void app_main(void) {
    uint64_t start = anx_uptime_ms();

    // ... do work ...
    anx_delay_ms(500);

    uint64_t elapsed = anx_uptime_ms() - start;
    ANX_LOGI("APP", "Elapsed: %llu ms", elapsed);
}
```

## Reboot Functions

### `anx_reboot()`

Performs a graceful system reboot: flushes any pending filesystem writes, closes open peripherals, and resets the processor. Use this instead of a hard reset to avoid filesystem corruption.

<ResponseField name="return" type="void">
  This function does not return. Execution resumes from the beginning of `app_main()` after the boot sequence completes.
</ResponseField>

***

### `anx_reboot_to_bootloader()`

Reboots the device directly into firmware flash mode. The device will appear as a firmware flashing target on its USB or serial interface and will not execute `app_main()` until a new firmware image is flashed or the device is power-cycled.

<ResponseField name="return" type="void">
  This function does not return.
</ResponseField>

<Note>
  Call `anx_reboot_to_bootloader()` only when you have confirmed that a firmware update tool is ready and connected. Entering flash mode without an active update session leaves the device unresponsive until power-cycled.
</Note>
