Files

332 lines
12 KiB
C

/*
* Copyright 2021-2023 Morse Micro
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @defgroup MMHAL Morse Micro Hardware Abstraction Layer (mmhal) API
*
* This API provides abstraction from the underlying hardware/BSP.
*
* @{
*/
#pragma once
#include "mmhal_flash.h"
#include "mmhal_wlan.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <time.h>
#ifdef __cplusplus
extern "C" {
#endif
/** Initialization before RTOS scheduler starts. */
void mmhal_early_init(void);
/** Initialization after RTOS scheduler started. */
void mmhal_init(void);
/** Enumeration of ISR states (i.e., whether in ISR or not). */
enum mmhal_isr_state {
MMHAL_NOT_IN_ISR, /**< The function was not executed from ISR context. */
MMHAL_IN_ISR, /**< The function was executed from ISR context. */
MMHAL_ISR_STATE_UNKNOWN, /**< The HAL does not support checking ISR state. */
};
/**
* Enumeration for different LED's on the board.
*
* @note Some of these LED's may not be available on all boards and some of these values
* may refer to the same LED.
*/
enum mmhal_led_id { LED_RED, LED_GREEN, LED_BLUE, LED_WHITE };
/** Enumeration of MCU sleep state. */
enum mmhal_sleep_state {
MMHAL_SLEEP_DISABLED, /**< Disable MCU sleep. */
MMHAL_SLEEP_SHALLOW, /**< MCU to enter shallow sleep. */
MMHAL_SLEEP_DEEP, /**< MCU can enter deep sleep. */
};
/** A value of 0 turns OFF an LED */
#define LED_OFF 0
/**
* A value of 255 turns an LED ON fully.
*
* Some boards support varying an LED's brightness. For these boards a value between 1 and 255
* will result in proportionately varying levels of brightness. LED's that do not have a
* brightness control feature will just turn ON fully for any non zero value.
*/
#define LED_ON 255
/**
* Get the current ISR state (i.e., whether in ISR or not).
*
* @returns the current ISR state, or @c MMHAL_ISR_STATE_UNKNOWN if the HAL does not support
* checking ISR state.
*/
enum mmhal_isr_state mmhal_get_isr_state(void);
/**
* Write to the debug log.
*
* It is assumed the caller will have mechanisms in place to prevent concurrent access.
*
* @param data Buffer containing data to write.
* @param len Length of data in buffer.
*/
void mmhal_log_write(const uint8_t *data, size_t len);
/**
* Flush the debug log before returning.
*
* @warning Implementations of this function must support being invoked with interrupts disabled.
*/
void mmhal_log_flush(void);
/**
* Generate a random 32 bit integer within the given range.
*
* @param min Minimum value (inclusive).
* @param max Maximum value (inclusive).
*
* @returns a randomly generated integer (min <= i <= max).
*/
uint32_t mmhal_random_u32(uint32_t min, uint32_t max);
/** Reset the microcontroller. */
void mmhal_reset(void);
/**
* Set the specified LED to the requested level. Do nothing if the requested LED does not exist.
*
* @param led The LED to set, if the platform supports it. See @ref mmhal_led_id
* @param level The level to set it to. 0 means OFF and non-zero means ON. If the platform supports
* brightness levels then 255 is full. Defines @ref LED_ON and @ref LED_OFF are
* provided for ease of use.
*/
void mmhal_set_led(uint8_t led, uint8_t level);
/**
* Set the error LED to the requested state.
*
* @note This function is called by the bootloader and so needs to do all the initialization
* required to set the LED's as the bootloader does not use the regular BSP initialization
* located in main.c for configuring @c GPIO's and setting clock gates as required.
*
* @param state Set to true if the LED needs to be turned on,
* or false if the led needs to be turned off.
*/
void mmhal_set_error_led(bool state);
/**
* Enumeration for buttons on the board.
*
* @note The support for each button is platform dependent.
*/
enum mmhal_button_id { BUTTON_ID_USER0 };
/**
* Enumeration for button states
*/
enum mmhal_button_state { BUTTON_RELEASED, BUTTON_PRESSED };
/** Button state callback function prototype. */
typedef void (*mmhal_button_state_cb_t)(enum mmhal_button_id button_id, enum mmhal_button_state button_state);
/**
* Registers a callback handler for button state changes.
*
* @note The callback will be executed in an Interrupt Service Routine context
*
* @param button_id The button whose state should be reported to the callback
* @param button_state_cb The function to call on button state change, or NULL to disable.
* @returns True if the callback is registered successfully, False if not supported
*/
bool mmhal_set_button_callback(enum mmhal_button_id button_id, mmhal_button_state_cb_t button_state_cb);
/**
* Returns the registered callback handler for button state changes.
*
* @param button_id The button whose callback should be returned
* @returns The registered callback or NULL if no callback registered
*/
mmhal_button_state_cb_t mmhal_get_button_callback(enum mmhal_button_id button_id);
/**
* Reads the state of the specified button.
*
* @param button_id The button state to read
* @returns The current button state, or BUTTON_RELEASED if not supported
*/
enum mmhal_button_state mmhal_get_button(enum mmhal_button_id button_id);
/**
* Reads information that can be used to identify the hardware platform, such as
* hardware ID and version number, in the form of a user readable string.
*
* This function attempts to detect the correct hardware and version.
* The actual means of detecting the correct hardware and version will vary from
* implementation to implementation and may use means such as identification
* information stored in EEPROM or devices detected on GPIO, SPI or I2C interfaces.
* Returns false if the hardware could not be identified correctly.
*
* @param version_buffer The pre-allocated buffer to return the hardware ID and version in.
* @param version_buffer_length The length of the pre-allocated buffer.
* @returns True if the hardware was correctly identified and returned.
*/
bool mmhal_get_hardware_version(char *version_buffer, size_t version_buffer_length);
/**
* Macro to simplify debug pin mask/value definition.
*
* @param _pin_num The pin number to set in the mask. Must be 0-31 (inclusive).
*
* Example:
*
* mmhal_set_debug_pins(MMHAL_DEBUG_PIN(0), MMHAL_DEBUG_PIN(0));
*/
#define MMHAL_DEBUG_PIN(_pin_num) (1ul << (_pin_num))
/** Bit mask with all debug pins selected. */
#define MMHAL_ALL_DEBUG_PINS (UINT32_MAX)
/**
* Set the value one or more debug pins.
*
* Each platform can define up to 32 GPIOs for application use. If a GPIO is not supported
* by a platform then attempts to set it will be silently ignored. These GPIOs are intended
* for debug/test purposes.
*
* @param mask Mask of GPIOs to modify. Each bit in this mask that is set will result in
* the corresponding GPIO being being set to the corresponding value given in
* @p values.
* @param values Bit field, where each bit corresponds to a GPIO, specifying the direction
* to drive each GPIO with 1 meaning drive high and 0 meaning drive low.
* Only GPIOs with the corresponding bit set in @p mask will be modified.
*
* @sa MM_DEBUG_PIN_MASK
*/
void mmhal_set_debug_pins(uint32_t mask, uint32_t values);
/**
* Returns the time of day as set in the RTC.
* Time is in UTC.
*
* @return Epoch time (seconds since 1 Jan 1970) or 0 on failure.
*/
time_t mmhal_get_time();
/**
* Sets the RTC to the specified time in UTC.
*
* @note While Unix epoch time supports years from 1970, most Real Time Clock
* chips support years from 2000 only as they store the year as years
* from 2000. So do not attempt to set any years below 2000 as this could cause
* the year to wrap around to an unreasonably high value. Definitely do not do:
* @code
* mmhal_set_time(0);
* @endcode
*
* @param epoch Time in Unix epoch time (seconds since 1 Jan 1970).
*/
void mmhal_set_time(time_t epoch);
/**
* Function to prepare MCU to enter sleep.
* This will halt the timer that generates the RTOS tick.
*
* @param expected_idle_time_ms Expected time to sleep in milliseconds.
*
* @returns the type of sleep permitted by the current system state.
*/
enum mmhal_sleep_state mmhal_sleep_prepare(uint32_t expected_idle_time_ms);
/**
* Function to enter MCU sleep.
*
* @param sleep_state Sleep state to enter into.
* @param expected_idle_time_ms Expected time to sleep in milliseconds.
*
* @returns Elapsed sleep time in milliseconds.
*/
uint32_t mmhal_sleep(enum mmhal_sleep_state sleep_state, uint32_t expected_idle_time_ms);
/**
* Function to abort the MCU sleep state.
*
* @note This must only be invoked after @ref mmhal_sleep_prepare()
* and before @ref mmhal_sleep().
*
* @param sleep_state Sleep state to abort.
*/
void mmhal_sleep_abort(enum mmhal_sleep_state sleep_state);
/**
* Function to cleanup on exit from the MCU sleep state.
*/
void mmhal_sleep_cleanup(void);
/** Enumeration of veto_id ranges for use with @ref mmhal_set_deep_sleep_veto() and
* @ref mmhal_clear_deep_sleep_veto(). */
enum mmhal_veto_id {
/** Start of deep sleep veto ID range that is available for application use. */
MMHAL_VETO_ID_APP_MIN = 0,
/** End of deep sleep veto ID range that is available for application use. */
MMHAL_VETO_ID_APP_MAX = 7,
/** Start of deep sleep veto ID range that is available for HAL use. */
MMHAL_VETO_ID_HAL_MIN = 8,
/** End of deep sleep veto ID range that is available for HAL use. */
MMHAL_VETO_ID_HAL_MAX = 15,
/** Start of deep sleep veto ID range that is allocated for morselib use. Note that this
* must not be changed as it is built into morselib. */
MMHAL_VETO_ID_MORSELIB_MIN = 16,
/** End of deep sleep veto ID range that is allocated for morselib use. Note that this must not
* be changed as it is built into morselib. */
MMHAL_VETO_ID_MORSELIB_MAX = 19,
/** Deep sleep veto ID for data-link subsystem. */
MMHAL_VETO_ID_DATALINK = 20,
/** Deep sleep veto ID allocated to @ref MMCONFIG. */
MMHAL_VETO_ID_MMCONFIG = 21,
/** Start of deep sleep veto ID range reserved for future use. */
MMHAL_VETO_ID_RESERVED_MIN = 22,
/** End of deep sleep veto ID range reserved for future use. */
MMHAL_VETO_ID_RESERVED_MAX = 31,
};
/**
* Sets a deep sleep veto that will prevent the device from entering deep sleep. The device
* will not enter deep sleep until there are no vetoes remaining. This veto can be cleared
* by a call to @ref mmhal_clear_deep_sleep_veto() with the same veto_id.
*
* Up to 32 vetoes are supported (ID numbers 0-31). Each veto should be used exclusively by
* a given aspect of the system (e.g., to prevent deep sleep when a DMA transfer is in progress,
* or to prevent deep sleep when there is log data buffered for transmit, etc.).
*
* @param veto_id The veto identifier. Valid values are 0-31, and these are split up into ranges
* for use by different subsystems -- see @ref mmhal_veto_id.
*/
void mmhal_set_deep_sleep_veto(uint8_t veto_id);
/**
* Clears a deep sleep veto that was preventing the device from entering deep sleep (see
* @ref mmhal_set_deep_sleep_veto()). If the given veto was not already set then this has
* no effect.
*
* @param veto_id The veto identifier. Valid values are 0-31, and these are split up into ranges
* for use by different subsystems -- see @ref mmhal_veto_id.
*/
void mmhal_clear_deep_sleep_veto(uint8_t veto_id);
#ifdef __cplusplus
}
#endif
/** @} */