Battery measurement, basic version
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
VERSION_MAJOR = 0
|
VERSION_MAJOR = 0
|
||||||
VERSION_MINOR = 0
|
VERSION_MINOR = 0
|
||||||
PATCHLEVEL = 6
|
PATCHLEVEL = 13
|
||||||
VERSION_TWEAK = 0
|
VERSION_TWEAK = 0
|
||||||
#if (IS_ENABLED(CONFIG_LOG))
|
#if (IS_ENABLED(CONFIG_LOG))
|
||||||
EXTRAVERSION = debug
|
EXTRAVERSION = debug
|
||||||
|
|||||||
@@ -54,7 +54,7 @@
|
|||||||
charger_status {
|
charger_status {
|
||||||
compatible = "gpio-keys";
|
compatible = "gpio-keys";
|
||||||
chg_status: chg_status {
|
chg_status: chg_status {
|
||||||
gpios = <&gpio0 13 GPIO_ACTIVE_HIGH>;
|
gpios = <&gpio0 13 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>;
|
||||||
label = "ETA6003_CHG_STATUS";
|
label = "ETA6003_CHG_STATUS";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
2
firmware/build_output.txt
Normal file
2
firmware/build_output.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
ERROR: Build directory /Users/edi/nrf_playground/buzzer_2/firmware/build targets board buzzy/nrf52840, but board {self.args.board} was specified. (Clean the directory, use --pristine, or use --build-dir to specify a different one.)
|
||||||
|
FATAL ERROR: refusing to proceed without --force due to above error
|
||||||
@@ -8,8 +8,16 @@ CONFIG_DEBUG_OPTIMIZATIONS=y
|
|||||||
CONFIG_INIT_STACKS=y
|
CONFIG_INIT_STACKS=y
|
||||||
CONFIG_THREAD_STACK_INFO=y
|
CONFIG_THREAD_STACK_INFO=y
|
||||||
|
|
||||||
### Bluetooth subsystem logging (reduced noise)
|
### Lib logging levels
|
||||||
CONFIG_BT_LOG_LEVEL_WRN=y
|
CONFIG_BATT_MGMT_LOG_LEVEL_DBG=y
|
||||||
|
CONFIG_USB_MGMT_LOG_LEVEL_DBG=y
|
||||||
|
|
||||||
|
### Bluetooth
|
||||||
|
CONFIG_BLE_MGMT=n
|
||||||
|
CONFIG_BT_LOG_LEVEL_WRN=n
|
||||||
|
|
||||||
|
### Audio
|
||||||
|
CONFIG_BUZZ_AUDIO=n
|
||||||
|
|
||||||
### Shell features shared by all debug variants
|
### Shell features shared by all debug variants
|
||||||
CONFIG_SHELL=y
|
CONFIG_SHELL=y
|
||||||
|
|||||||
@@ -5,3 +5,5 @@ add_subdirectory(ble_mgmt)
|
|||||||
add_subdirectory(buzz_proto)
|
add_subdirectory(buzz_proto)
|
||||||
add_subdirectory(audio)
|
add_subdirectory(audio)
|
||||||
add_subdirectory(event_mgmt)
|
add_subdirectory(event_mgmt)
|
||||||
|
add_subdirectory(batt_mgmt)
|
||||||
|
add_subdirectory(usb_mgmt)
|
||||||
@@ -5,3 +5,5 @@ rsource "ble_mgmt/Kconfig"
|
|||||||
rsource "buzz_proto/Kconfig"
|
rsource "buzz_proto/Kconfig"
|
||||||
rsource "audio/Kconfig"
|
rsource "audio/Kconfig"
|
||||||
rsource "event_mgmt/Kconfig"
|
rsource "event_mgmt/Kconfig"
|
||||||
|
rsource "batt_mgmt/Kconfig"
|
||||||
|
rsource "usb_mgmt/Kconfig"
|
||||||
|
|||||||
5
firmware/libs/batt_mgmt/CMakeLists.txt
Normal file
5
firmware/libs/batt_mgmt/CMakeLists.txt
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
if(CONFIG_BATT_MGMT)
|
||||||
|
zephyr_library()
|
||||||
|
zephyr_library_sources(src/batt_mgmt.c)
|
||||||
|
zephyr_include_directories(include)
|
||||||
|
endif()
|
||||||
63
firmware/libs/batt_mgmt/Kconfig
Normal file
63
firmware/libs/batt_mgmt/Kconfig
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
menuconfig BATT_MGMT
|
||||||
|
bool "Battery Management"
|
||||||
|
default y
|
||||||
|
select ADC
|
||||||
|
select GPIO
|
||||||
|
select USB_MGMT
|
||||||
|
help
|
||||||
|
Library for initializing and managing the battery subsystem.
|
||||||
|
|
||||||
|
if BATT_MGMT
|
||||||
|
config BATT_MGMT_FULL_THRESHOLD
|
||||||
|
int "Battery Full Voltage (mV)"
|
||||||
|
default 3980
|
||||||
|
help
|
||||||
|
Set the voltage level (in millivolts) that represents a full battery. Default is 3980 mV.
|
||||||
|
|
||||||
|
config BATT_MGMT_80P_THRESHOLD
|
||||||
|
int "Battery 80% Voltage (mV)"
|
||||||
|
default 3820
|
||||||
|
help
|
||||||
|
Set the voltage level (in millivolts) that represents 80% battery. Default is 3820 mV.
|
||||||
|
|
||||||
|
config BATT_MGMT_50P_THRESHOLD
|
||||||
|
int "Battery 50% Voltage (mV)"
|
||||||
|
default 3720
|
||||||
|
help
|
||||||
|
Set the voltage level (in millivolts) that represents 50% battery. Default is 3720 mV.
|
||||||
|
|
||||||
|
config BATT_MGMT_20P_THRESHOLD
|
||||||
|
int "Battery 20% Voltage (mV)"
|
||||||
|
default 3620
|
||||||
|
help
|
||||||
|
Set the voltage level (in millivolts) that represents 20% battery. Default is 3620 mV.
|
||||||
|
|
||||||
|
config BATT_MGMT_CHG_BLINKING_WINDOW_MS
|
||||||
|
int "Charger blinking detection window (ms)"
|
||||||
|
default 700
|
||||||
|
help
|
||||||
|
Time window to detect charger pin blinking (state changes). If the pin state
|
||||||
|
changes within this window, it's considered blinking (error state).
|
||||||
|
|
||||||
|
config BATT_MGMT_MONITOR_THREAD_STACK_SIZE
|
||||||
|
int "Battery monitor thread stack size"
|
||||||
|
default 1024
|
||||||
|
help
|
||||||
|
Stack size for the USB-triggered charger status monitor thread.
|
||||||
|
|
||||||
|
config BATT_MGMT_MONITOR_THREAD_PRIORITY
|
||||||
|
int "Battery monitor thread priority"
|
||||||
|
default 7
|
||||||
|
help
|
||||||
|
Cooperative priority for the monitor thread (lower number = higher priority).
|
||||||
|
|
||||||
|
config BATT_MGMT_BLINK_INTERVAL_LOGGING
|
||||||
|
bool "Enable logging of charger pin blinking intervals"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
If enabled, logs the time intervals between charger pin state changes, which can help diagnose charger connection issues.
|
||||||
|
|
||||||
|
module = BATT_MGMT
|
||||||
|
module-str = batt_mgmt
|
||||||
|
source "subsys/logging/Kconfig.template.log_config"
|
||||||
|
endif # BATT_MGMT
|
||||||
52
firmware/libs/batt_mgmt/include/batt_mgmt.h
Normal file
52
firmware/libs/batt_mgmt/include/batt_mgmt.h
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#ifndef BATT_MGMT_H
|
||||||
|
#define BATT_MGMT_H
|
||||||
|
|
||||||
|
#include <zephyr/types.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#define BATT_MGMT_OVERSAMPLING_8X 8U
|
||||||
|
#define BATT_MGMT_OVERSAMPLING_16X 16U
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
BATT_STATE_DISCHARGING = 0,
|
||||||
|
BATT_STATE_FULL,
|
||||||
|
BATT_STATE_CHARGING,
|
||||||
|
BATT_STATE_ERROR,
|
||||||
|
BATT_STATE_UNKNOWN,
|
||||||
|
} batt_mgmt_state_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Measure battery VDDH voltage.
|
||||||
|
*
|
||||||
|
* @param oversampling Oversampling factor (BATT_MGMT_OVERSAMPLING_8X or BATT_MGMT_OVERSAMPLING_16X).
|
||||||
|
* @param vddh_mv Pointer to store the result in millivolts.
|
||||||
|
* @return 0 on success, negative errno on failure.
|
||||||
|
*/
|
||||||
|
int batt_mgmt_measure_vddh_mv(uint8_t oversampling, int32_t *vddh_mv);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get raw charger status (GPIO level).
|
||||||
|
*
|
||||||
|
* Returns the current logic level of the charger status pin (typically from ETA6003).
|
||||||
|
* This is the **raw GPIO status**, not a processed state machine result.
|
||||||
|
*
|
||||||
|
* @return true if charger pin is high (e.g., battery is "full"), false if low.
|
||||||
|
*/
|
||||||
|
bool batt_mgmt_get_charger_status(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get processed battery state with blinking detection.
|
||||||
|
*
|
||||||
|
* Returns a derived state based on:
|
||||||
|
* - USB VBUS presence (from usb_mgmt)
|
||||||
|
* - Charger status GPIO level (from batt_mgmt_get_charger_status)
|
||||||
|
* - Blinking detection (state changes within CONFIG_BATT_MGMT_CHG_BLINKING_WINDOW_MS)
|
||||||
|
*
|
||||||
|
* Note: This differs from batt_mgmt_get_charger_status() which returns the **raw** GPIO level.
|
||||||
|
*
|
||||||
|
* @return Battery state enum (DISCHARGING, FULL, CHARGING, or ERROR if blinking detected).
|
||||||
|
*/
|
||||||
|
batt_mgmt_state_t batt_mgmt_get_battery_state(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
313
firmware/libs/batt_mgmt/src/batt_mgmt.c
Normal file
313
firmware/libs/batt_mgmt/src/batt_mgmt.c
Normal file
@@ -0,0 +1,313 @@
|
|||||||
|
#include <zephyr/device.h>
|
||||||
|
#include <zephyr/drivers/adc.h>
|
||||||
|
#include <zephyr/drivers/gpio.h>
|
||||||
|
#include <zephyr/init.h>
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
#include <zephyr/logging/log.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "batt_mgmt.h"
|
||||||
|
#include "usb_mgmt.h"
|
||||||
|
|
||||||
|
LOG_MODULE_REGISTER(batt_mgmt, CONFIG_BATT_MGMT_LOG_LEVEL);
|
||||||
|
|
||||||
|
#define BATT_VDDH_DIVIDER_FACTOR 5
|
||||||
|
|
||||||
|
#define BATT_VDDH_ADC_NODE DT_PATH(zephyr_user)
|
||||||
|
static const struct adc_dt_spec batt_vddh_adc = ADC_DT_SPEC_GET_BY_NAME(BATT_VDDH_ADC_NODE, vddh);
|
||||||
|
|
||||||
|
#define BATT_CHG_STATUS_NODE DT_ALIAS(chg_status)
|
||||||
|
static const struct gpio_dt_spec batt_chg_status = GPIO_DT_SPEC_GET(BATT_CHG_STATUS_NODE, gpios);
|
||||||
|
|
||||||
|
static bool batt_mgmt_ready;
|
||||||
|
static int64_t batt_mgmt_last_chg_change_ms;
|
||||||
|
static bool batt_mgmt_chg_interrupt_enabled;
|
||||||
|
static K_THREAD_STACK_DEFINE(batt_monitor_stack, CONFIG_BATT_MGMT_MONITOR_THREAD_STACK_SIZE);
|
||||||
|
static struct k_thread batt_monitor_thread_data;
|
||||||
|
|
||||||
|
static int batt_mgmt_to_adc_oversampling(uint8_t oversampling, uint8_t *adc_oversampling)
|
||||||
|
{
|
||||||
|
if (adc_oversampling == NULL)
|
||||||
|
{
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (oversampling)
|
||||||
|
{
|
||||||
|
case BATT_MGMT_OVERSAMPLING_8X:
|
||||||
|
*adc_oversampling = 3U;
|
||||||
|
return 0;
|
||||||
|
case BATT_MGMT_OVERSAMPLING_16X:
|
||||||
|
*adc_oversampling = 4U;
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int batt_mgmt_measure_vddh_mv(uint8_t oversampling, int32_t *vddh_mv)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
uint8_t adc_oversampling;
|
||||||
|
int16_t raw_sample;
|
||||||
|
int32_t input_mv;
|
||||||
|
struct adc_sequence sequence = {
|
||||||
|
.buffer = &raw_sample,
|
||||||
|
.buffer_size = sizeof(raw_sample),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (vddh_mv == NULL)
|
||||||
|
{
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!batt_mgmt_ready)
|
||||||
|
{
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = batt_mgmt_to_adc_oversampling(oversampling, &adc_oversampling);
|
||||||
|
if (rc < 0)
|
||||||
|
{
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = adc_sequence_init_dt(&batt_vddh_adc, &sequence);
|
||||||
|
if (rc < 0)
|
||||||
|
{
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
sequence.oversampling = adc_oversampling;
|
||||||
|
|
||||||
|
rc = adc_read_dt(&batt_vddh_adc, &sequence);
|
||||||
|
if (rc < 0)
|
||||||
|
{
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
input_mv = raw_sample;
|
||||||
|
rc = adc_raw_to_millivolts_dt(&batt_vddh_adc, &input_mv);
|
||||||
|
if (rc < 0)
|
||||||
|
{
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
*vddh_mv = input_mv * BATT_VDDH_DIVIDER_FACTOR;
|
||||||
|
|
||||||
|
LOG_DBG("Battery VDDH: %d mV (raw=%d, os=%ux)", *vddh_mv, raw_sample, oversampling);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void batt_mgmt_chg_interrupt_handler(const struct device *dev,
|
||||||
|
struct gpio_callback *cb,
|
||||||
|
uint32_t pins)
|
||||||
|
{
|
||||||
|
int64_t now_ms = k_uptime_get();
|
||||||
|
int64_t delta_ms = now_ms - batt_mgmt_last_chg_change_ms;
|
||||||
|
|
||||||
|
#ifdef CONFIG_BATT_MGMT_BLINK_INTERVAL_LOGGING
|
||||||
|
LOG_DBG("CHG interrupt: delta=%lld ms", delta_ms);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
batt_mgmt_last_chg_change_ms = now_ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int batt_mgmt_enable_chg_interrupt(void)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
static struct gpio_callback batt_chg_cb;
|
||||||
|
|
||||||
|
if (batt_mgmt_chg_interrupt_enabled)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gpio_is_ready_dt(&batt_chg_status))
|
||||||
|
{
|
||||||
|
LOG_ERR("CHG GPIO device not ready");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = gpio_pin_configure_dt(&batt_chg_status, GPIO_INPUT);
|
||||||
|
if (rc < 0)
|
||||||
|
{
|
||||||
|
LOG_ERR("Failed to configure CHG GPIO: %d", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
gpio_init_callback(&batt_chg_cb, batt_mgmt_chg_interrupt_handler, BIT(batt_chg_status.pin));
|
||||||
|
rc = gpio_add_callback(batt_chg_status.port, &batt_chg_cb);
|
||||||
|
if (rc < 0)
|
||||||
|
{
|
||||||
|
LOG_ERR("Failed to add CHG callback: %d", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = gpio_pin_interrupt_configure_dt(&batt_chg_status, GPIO_INT_EDGE_BOTH);
|
||||||
|
if (rc < 0)
|
||||||
|
{
|
||||||
|
LOG_ERR("Failed to configure CHG interrupt: %d", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
batt_mgmt_chg_interrupt_enabled = true;
|
||||||
|
batt_mgmt_last_chg_change_ms = k_uptime_get();
|
||||||
|
LOG_INF("CHG interrupt enabled");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int batt_mgmt_disable_chg_interrupt(void)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (!batt_mgmt_chg_interrupt_enabled)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = gpio_pin_interrupt_configure_dt(&batt_chg_status, GPIO_INT_DISABLE);
|
||||||
|
if (rc < 0)
|
||||||
|
{
|
||||||
|
LOG_WRN("Failed to disable CHG interrupt: %d", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = gpio_pin_configure(batt_chg_status.port, batt_chg_status.pin, GPIO_DISCONNECTED);
|
||||||
|
if (rc < 0)
|
||||||
|
{
|
||||||
|
LOG_WRN("Failed to disconnect CHG GPIO: %d", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
batt_mgmt_chg_interrupt_enabled = false;
|
||||||
|
LOG_DBG("CHG interrupt disabled");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool batt_mgmt_get_charger_status(void)
|
||||||
|
{
|
||||||
|
if (!batt_mgmt_chg_interrupt_enabled)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return gpio_pin_get_dt(&batt_chg_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
batt_mgmt_state_t batt_mgmt_get_battery_state(void)
|
||||||
|
{
|
||||||
|
int64_t now_ms = k_uptime_get();
|
||||||
|
int64_t delta_ms = now_ms - batt_mgmt_last_chg_change_ms;
|
||||||
|
bool chg_high = batt_mgmt_get_charger_status();
|
||||||
|
bool usb_present = usb_mgmt_is_vbus_present();
|
||||||
|
|
||||||
|
/* Blinking detection: state change within window */
|
||||||
|
if (delta_ms < CONFIG_BATT_MGMT_CHG_BLINKING_WINDOW_MS)
|
||||||
|
{
|
||||||
|
LOG_DBG("Blinking detected (delta=%lld ms)", delta_ms);
|
||||||
|
return BATT_STATE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stable states */
|
||||||
|
if (chg_high)
|
||||||
|
{
|
||||||
|
return BATT_STATE_CHARGING;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usb_present)
|
||||||
|
{
|
||||||
|
return BATT_STATE_FULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BATT_STATE_DISCHARGING;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void batt_mgmt_monitor_thread(void *unused1, void *unused2, void *unused3)
|
||||||
|
{
|
||||||
|
(void)unused1;
|
||||||
|
(void)unused2;
|
||||||
|
(void)unused3;
|
||||||
|
|
||||||
|
if (!usb_mgmt_wait_ready(K_SECONDS(2)))
|
||||||
|
{
|
||||||
|
LOG_WRN("usb_mgmt not ready after timeout; using current VBUS state");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sync initial state in case VBUS was already present before this thread started. */
|
||||||
|
bool vbus_present = usb_mgmt_is_vbus_present();
|
||||||
|
|
||||||
|
if (vbus_present)
|
||||||
|
{
|
||||||
|
(void)batt_mgmt_enable_chg_interrupt();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
(void)batt_mgmt_disable_chg_interrupt();
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
uint32_t events = k_event_wait(&usb_mgmt_events,
|
||||||
|
USB_MGMT_VBUS_CONNECTED | USB_MGMT_VBUS_DISCONNECTED,
|
||||||
|
false, K_FOREVER);
|
||||||
|
|
||||||
|
if (events & USB_MGMT_VBUS_CONNECTED)
|
||||||
|
{
|
||||||
|
(void)batt_mgmt_enable_chg_interrupt();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (events & USB_MGMT_VBUS_DISCONNECTED)
|
||||||
|
{
|
||||||
|
(void)batt_mgmt_disable_chg_interrupt();
|
||||||
|
}
|
||||||
|
|
||||||
|
k_event_clear(&usb_mgmt_events, USB_MGMT_VBUS_CONNECTED | USB_MGMT_VBUS_DISCONNECTED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int batt_mgmt_init(void)
|
||||||
|
{
|
||||||
|
int32_t boot_vddh_mv;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (!adc_is_ready_dt(&batt_vddh_adc))
|
||||||
|
{
|
||||||
|
LOG_ERR("VDDH ADC device not ready");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = adc_channel_setup_dt(&batt_vddh_adc);
|
||||||
|
if (rc < 0)
|
||||||
|
{
|
||||||
|
LOG_ERR("VDDH ADC channel setup failed: %d", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
batt_mgmt_ready = true;
|
||||||
|
|
||||||
|
rc = batt_mgmt_measure_vddh_mv(BATT_MGMT_OVERSAMPLING_16X, &boot_vddh_mv);
|
||||||
|
if (rc < 0)
|
||||||
|
{
|
||||||
|
LOG_WRN("Initial battery measurement failed: %d", rc);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_DBG("Initial battery VDDH: %d mV", boot_vddh_mv);
|
||||||
|
|
||||||
|
k_thread_create(&batt_monitor_thread_data,
|
||||||
|
batt_monitor_stack,
|
||||||
|
K_THREAD_STACK_SIZEOF(batt_monitor_stack),
|
||||||
|
batt_mgmt_monitor_thread,
|
||||||
|
NULL, NULL, NULL,
|
||||||
|
K_PRIO_COOP(CONFIG_BATT_MGMT_MONITOR_THREAD_PRIORITY),
|
||||||
|
0, K_NO_WAIT);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SYS_INIT(batt_mgmt_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
|
||||||
@@ -27,7 +27,11 @@ LOG_MODULE_REGISTER(settings_mgmt, LOG_LEVEL_INF);
|
|||||||
|
|
||||||
/* The "Source of Truth" in RAM */
|
/* The "Source of Truth" in RAM */
|
||||||
struct app_settings_t app_cfg = {
|
struct app_settings_t app_cfg = {
|
||||||
|
#ifdef CONFIG_BLE_MGMT_DEFAULT_DEVICE_NAME
|
||||||
.dev_name = CONFIG_BLE_MGMT_DEFAULT_DEVICE_NAME,
|
.dev_name = CONFIG_BLE_MGMT_DEFAULT_DEVICE_NAME,
|
||||||
|
#else
|
||||||
|
.dev_name = CONFIG_BOARD, /* Default to board name if no explicit default set */
|
||||||
|
#endif
|
||||||
.vol = 100, /* 0-100 % */
|
.vol = 100, /* 0-100 % */
|
||||||
.shuffle_mode = 0,
|
.shuffle_mode = 0,
|
||||||
.ble_timeout = 0xFFFFFFFF,
|
.ble_timeout = 0xFFFFFFFF,
|
||||||
|
|||||||
5
firmware/libs/usb_mgmt/CMakeLists.txt
Normal file
5
firmware/libs/usb_mgmt/CMakeLists.txt
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
if(CONFIG_USB_MGMT)
|
||||||
|
zephyr_library()
|
||||||
|
zephyr_library_sources(src/usb_mgmt.c)
|
||||||
|
zephyr_include_directories(include)
|
||||||
|
endif()
|
||||||
13
firmware/libs/usb_mgmt/Kconfig
Normal file
13
firmware/libs/usb_mgmt/Kconfig
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
menuconfig USB_MGMT
|
||||||
|
bool "USB Management"
|
||||||
|
default y
|
||||||
|
select NRFX_POWER
|
||||||
|
help
|
||||||
|
Library for USB-related queries, e.g. VBUS presence detection
|
||||||
|
via the nRF52840 POWER peripheral.
|
||||||
|
|
||||||
|
if USB_MGMT
|
||||||
|
module = USB_MGMT
|
||||||
|
module-str = usb_mgmt
|
||||||
|
source "subsys/logging/Kconfig.template.log_config"
|
||||||
|
endif # USB_MGMT
|
||||||
30
firmware/libs/usb_mgmt/include/usb_mgmt.h
Normal file
30
firmware/libs/usb_mgmt/include/usb_mgmt.h
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
#ifndef USB_MGMT_H
|
||||||
|
#define USB_MGMT_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
|
||||||
|
#define USB_MGMT_VBUS_CONNECTED BIT(0)
|
||||||
|
#define USB_MGMT_VBUS_DISCONNECTED BIT(1)
|
||||||
|
|
||||||
|
extern struct k_event usb_mgmt_events;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Wait until usb_mgmt has completed initialization.
|
||||||
|
*
|
||||||
|
* @param timeout Timeout for waiting.
|
||||||
|
*
|
||||||
|
* @retval true usb_mgmt is ready.
|
||||||
|
* @retval false timeout occurred.
|
||||||
|
*/
|
||||||
|
bool usb_mgmt_wait_ready(k_timeout_t timeout);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns true when VBUS (USB 5 V) is present.
|
||||||
|
*
|
||||||
|
* Reads the USBREGSTATUS.VBUSDETECT bit in the nRF52840 POWER peripheral.
|
||||||
|
* No USB stack needs to be enabled.
|
||||||
|
*/
|
||||||
|
bool usb_mgmt_is_vbus_present(void);
|
||||||
|
|
||||||
|
#endif /* USB_MGMT_H */
|
||||||
65
firmware/libs/usb_mgmt/src/usb_mgmt.c
Normal file
65
firmware/libs/usb_mgmt/src/usb_mgmt.c
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
#include <hal/nrf_power.h>
|
||||||
|
#include <nrfx_power.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <zephyr/logging/log.h>
|
||||||
|
|
||||||
|
#include "usb_mgmt.h"
|
||||||
|
|
||||||
|
LOG_MODULE_REGISTER(usb_mgmt, CONFIG_USB_MGMT_LOG_LEVEL);
|
||||||
|
|
||||||
|
K_EVENT_DEFINE(usb_mgmt_events);
|
||||||
|
K_SEM_DEFINE(usb_mgmt_ready_sem, 0, 1);
|
||||||
|
|
||||||
|
static bool usb_mgmt_last_vbus_state;
|
||||||
|
static bool usb_mgmt_ready;
|
||||||
|
|
||||||
|
static void usb_mgmt_power_handler(nrfx_power_usb_evt_t event)
|
||||||
|
{
|
||||||
|
bool is_present = (event == NRFX_POWER_USB_EVT_DETECTED);
|
||||||
|
|
||||||
|
LOG_INF("VBUS %s (event=%u)", is_present ? "connected" : "disconnected", event);
|
||||||
|
|
||||||
|
if (is_present != usb_mgmt_last_vbus_state) {
|
||||||
|
usb_mgmt_last_vbus_state = is_present;
|
||||||
|
k_event_post(&usb_mgmt_events,
|
||||||
|
is_present ? USB_MGMT_VBUS_CONNECTED : USB_MGMT_VBUS_DISCONNECTED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usb_mgmt_init(void)
|
||||||
|
{
|
||||||
|
usb_mgmt_last_vbus_state = nrf_power_usbregstatus_vbusdet_get(NRF_POWER);
|
||||||
|
LOG_DBG("Boot VBUS state: %s", usb_mgmt_last_vbus_state ? "present" : "absent");
|
||||||
|
k_event_post(&usb_mgmt_events,
|
||||||
|
usb_mgmt_last_vbus_state ? USB_MGMT_VBUS_CONNECTED : USB_MGMT_VBUS_DISCONNECTED);
|
||||||
|
|
||||||
|
nrfx_power_config_t config = { 0 };
|
||||||
|
nrfx_power_usbevt_config_t usb_config = {
|
||||||
|
.handler = usb_mgmt_power_handler,
|
||||||
|
};
|
||||||
|
|
||||||
|
nrfx_power_init(&config);
|
||||||
|
nrfx_power_usbevt_init(&usb_config);
|
||||||
|
nrfx_power_usbevt_enable();
|
||||||
|
|
||||||
|
usb_mgmt_ready = true;
|
||||||
|
k_sem_give(&usb_mgmt_ready_sem);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SYS_INIT(usb_mgmt_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
|
||||||
|
|
||||||
|
bool usb_mgmt_is_vbus_present(void)
|
||||||
|
{
|
||||||
|
return usb_mgmt_last_vbus_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool usb_mgmt_wait_ready(k_timeout_t timeout)
|
||||||
|
{
|
||||||
|
if (usb_mgmt_ready) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return k_sem_take(&usb_mgmt_ready_sem, timeout) == 0;
|
||||||
|
}
|
||||||
2
firmware/output.txt
Normal file
2
firmware/output.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
ERROR: Build directory /Users/edi/nrf_playground/buzzer_2/firmware/build targets board buzzy/nrf52840, but board {self.args.board} was specified. (Clean the directory, use --pristine, or use --build-dir to specify a different one.)
|
||||||
|
FATAL ERROR: refusing to proceed without --force due to above error
|
||||||
@@ -1,9 +1,3 @@
|
|||||||
### Bluetooth
|
|
||||||
CONFIG_BLE_MGMT=y
|
|
||||||
|
|
||||||
### Audio
|
|
||||||
CONFIG_BUZZ_AUDIO=n
|
|
||||||
|
|
||||||
### Error handling
|
### Error handling
|
||||||
CONFIG_HW_STACK_PROTECTION=y
|
CONFIG_HW_STACK_PROTECTION=y
|
||||||
CONFIG_RESET_ON_FATAL_ERROR=y
|
CONFIG_RESET_ON_FATAL_ERROR=y
|
||||||
@@ -11,6 +5,9 @@ CONFIG_RESET_ON_FATAL_ERROR=y
|
|||||||
### Power management
|
### Power management
|
||||||
CONFIG_PM_DEVICE=y
|
CONFIG_PM_DEVICE=y
|
||||||
|
|
||||||
|
### Boot banner
|
||||||
|
CONFIG_NCS_APPLICATION_BOOT_BANNER_STRING="Edis Buzzer"
|
||||||
|
|
||||||
### Stack
|
### Stack
|
||||||
CONFIG_MAIN_STACK_SIZE=2048
|
CONFIG_MAIN_STACK_SIZE=2048
|
||||||
CONFIG_BT_RX_STACK_SIZE=4096
|
CONFIG_BT_RX_STACK_SIZE=4096
|
||||||
|
|||||||
5
firmware/rtt_script.jlink
Normal file
5
firmware/rtt_script.jlink
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
connect
|
||||||
|
rtt start
|
||||||
|
sleep 3000
|
||||||
|
rtt stop
|
||||||
|
exit
|
||||||
@@ -4,11 +4,28 @@
|
|||||||
|
|
||||||
#include "buzz_proto.h"
|
#include "buzz_proto.h"
|
||||||
#include "settings_mgmt.h"
|
#include "settings_mgmt.h"
|
||||||
|
#include "batt_mgmt.h"
|
||||||
// #include "fw_mgmt.h"
|
// #include "fw_mgmt.h"
|
||||||
// #include "audio.h"
|
// #include "audio.h"
|
||||||
|
|
||||||
LOG_MODULE_REGISTER(main);
|
LOG_MODULE_REGISTER(main);
|
||||||
|
|
||||||
|
static const char *battery_state_to_str(batt_mgmt_state_t state)
|
||||||
|
{
|
||||||
|
switch (state) {
|
||||||
|
case BATT_STATE_DISCHARGING:
|
||||||
|
return "discharging";
|
||||||
|
case BATT_STATE_FULL:
|
||||||
|
return "full";
|
||||||
|
case BATT_STATE_CHARGING:
|
||||||
|
return "charging";
|
||||||
|
case BATT_STATE_ERROR:
|
||||||
|
return "error";
|
||||||
|
default:
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_BLE_MGMT)
|
#if IS_ENABLED(CONFIG_BLE_MGMT)
|
||||||
#include "ble_mgmt.h"
|
#include "ble_mgmt.h"
|
||||||
void ble_rx_cb(const uint8_t *data, uint16_t len)
|
void ble_rx_cb(const uint8_t *data, uint16_t len)
|
||||||
@@ -49,6 +66,7 @@ void ble_rx_cb(const uint8_t *data, uint16_t len)
|
|||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_BLE_MGMT)
|
#if IS_ENABLED(CONFIG_BLE_MGMT)
|
||||||
/* BLE-Subsystem initialisieren und RX-Callback registrieren */
|
/* BLE-Subsystem initialisieren und RX-Callback registrieren */
|
||||||
int rc = ble_mgmt_init(ble_rx_cb, app_cfg.dev_name);
|
int rc = ble_mgmt_init(ble_rx_cb, app_cfg.dev_name);
|
||||||
@@ -56,17 +74,25 @@ int main(void)
|
|||||||
LOG_ERR("Failed to initialize BLE management: %d", rc);
|
LOG_ERR("Failed to initialize BLE management: %d", rc);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
LOG_WRN("After BLE init");
|
|
||||||
#else
|
#else
|
||||||
LOG_WRN("BLE not enabled");
|
LOG_WRN("BLE not enabled");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
LOG_WRN("Main park loop active");
|
|
||||||
|
|
||||||
// k_sleep(K_MSEC(500));
|
#if IS_ENABLED(CONFIG_BATT_MGMT)
|
||||||
// LOG_INF("Playing test audio files...");
|
k_sleep(K_MSEC(100));
|
||||||
// audio_queue_play("/lfs/sys/update", false);
|
int32_t batt_mv;
|
||||||
// audio_queue_play("/lfs/sys/confirm", false);
|
int batt_rc = batt_mgmt_measure_vddh_mv(BATT_MGMT_OVERSAMPLING_16X, &batt_mv);
|
||||||
|
if (batt_rc == 0) {
|
||||||
|
LOG_INF("Battery after boot: %d mV", batt_mv);
|
||||||
|
} else {
|
||||||
|
LOG_WRN("Battery measurement after boot failed: %d", batt_rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
k_sleep(K_SECONDS(1));
|
||||||
|
batt_mgmt_state_t batt_state = batt_mgmt_get_battery_state();
|
||||||
|
LOG_INF("Battery state after 1s: %s (%d)", battery_state_to_str(batt_state), batt_state);
|
||||||
|
#endif
|
||||||
for (;;) {
|
for (;;) {
|
||||||
int32_t rem_ms = k_sleep(K_FOREVER);
|
int32_t rem_ms = k_sleep(K_FOREVER);
|
||||||
LOG_WRN("main woke unexpectedly (remaining=%d ms)", rem_ms);
|
LOG_WRN("main woke unexpectedly (remaining=%d ms)", rem_ms);
|
||||||
|
|||||||
Reference in New Issue
Block a user