This commit is contained in:
2026-02-26 15:44:43 +01:00
parent b8b3e6ea44
commit 5934bba4af
7 changed files with 159 additions and 16 deletions

View File

@@ -1 +1,2 @@
CONFIG_NRFX_POWER=y
CONFIG_NRFX_POWER=y
CONFIG_BT=n

View File

@@ -6,6 +6,7 @@
status-led = &led2;
buzzer-button = &button0;
audio-i2s = &i2s0;
audio-amp-en = &audio_amp_en;
usb-uart = &cdc_acm_uart0;
qspi-flash = &mx25r64;
};
@@ -17,6 +18,14 @@
zephyr,user {
usb-detect-gpios = <&gpio1 1 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>;
};
amp {
compatible = "gpio-leds";
audio_amp_en: audio_amp_en {
gpios = <&gpio0 28 GPIO_ACTIVE_HIGH>;
label = "Amplifier Shudown Pin";
};
};
};
&usbd {
@@ -52,4 +61,17 @@
pinctrl-0 = <&i2s0_default>;
pinctrl-1 = <&i2s0_sleep>;
pinctrl-names = "default", "sleep";
};
};
// &uart0 { status = "disabled"; };
&i2c0 { status = "disabled"; };
&spi1 { status = "disabled"; };
&spi3 { status = "disabled"; };
&adc { status = "disabled"; };
&nfct { status = "disabled"; };
&temp { status = "disabled"; };
&pwm0 { status = "disabled"; };
&radio { status = "disabled"; };
&ieee802154 { status = "disabled"; };
&bt_hci_sdc { status = "disabled"; };
&cryptocell { status = "disabled"; };

View File

@@ -42,5 +42,10 @@ CONFIG_NRFX_I2S=y
# --- Random & HW Info (für Audio-File-Auswahl) ---
CONFIG_HWINFO=y
CONFIG_ENTROPY_GENERATOR=y
CONFIG_CRC=y
CONFIG_CRC=y
# --- Unbenutze Features ---
CONFIG_ADC=n
CONFIG_I2C=n
CONFIG_SPI=n
CONFIG_PWM=n

View File

@@ -3,6 +3,7 @@
#include <zephyr/device.h>
#include <zephyr/drivers/i2s.h>
#include <zephyr/pm/device.h>
#include <zephyr/drivers/gpio.h>
#include <string.h>
#include <audio.h>
@@ -29,13 +30,42 @@ K_SEM_DEFINE(audio_ready_sem, 0, 1);
#error "Audio I2S alias not defined in devicetree"
#endif
#define AUDIO_AMP_ENABLE_NODE DT_ALIAS(audio_amp_en)
#if !DT_NODE_EXISTS(AUDIO_AMP_ENABLE_NODE)
#error "Audio Amplifier Enable alias not defined in devicetree"
#endif
static const struct device *const i2s_dev = DEVICE_DT_GET(I2S_NODE);
static const struct gpio_dt_spec amp_en_dev = GPIO_DT_SPEC_GET(AUDIO_AMP_ENABLE_NODE, gpios);
static volatile bool abort_playback = false;
static char next_random_filename[64] = {0};
static uint32_t audio_file_count = 0;
static char cached_404_path[] = "/lfs/sys/404";
void i2s_suspend(void)
{
LOG_DBG("Suspending I2S interface for power saving");
i2s_trigger(i2s_dev, I2S_DIR_TX, I2S_TRIGGER_DROP);
/* Nutzt jetzt die korrekte Spezifikation */
gpio_pin_set_dt(&amp_en_dev, 0);
pm_device_action_run(i2s_dev, PM_DEVICE_ACTION_SUSPEND);
}
void i2s_resume(void)
{
LOG_DBG("Resuming I2S interface");
/* Zuerst Pin auf High, dann Hardware wecken */
gpio_pin_set_dt(&amp_en_dev, 1);
pm_device_action_run(i2s_dev, PM_DEVICE_ACTION_RESUME);
}
void audio_refresh_file_count(void)
{
struct fs_dir_t dirp;
@@ -142,6 +172,7 @@ void audio_thread(void *arg1, void *arg2, void *arg3)
{
LOG_DBG("Audio thread started");
k_sem_take(&audio_ready_sem, K_FOREVER);
i2s_suspend();
/* Ersten zufälligen Dateinamen beim Booten vorab cachen */
get_random_file(next_random_filename, sizeof(next_random_filename));
@@ -152,9 +183,8 @@ void audio_thread(void *arg1, void *arg2, void *arg3)
{
if (k_msgq_get(&audio_play_msgq, &filename, K_FOREVER) == 0)
{
fs_pm_flash_resume();
abort_playback = false;
i2s_resume();
/* 2. Datei bestimmen (aus Cache oder synchron als Fallback) */
if (filename[0] == '\0')
@@ -178,7 +208,7 @@ void audio_thread(void *arg1, void *arg2, void *arg3)
struct fs_file_t file;
fs_file_t_init(&file);
if (fs_open(&file, filename, FS_O_READ) < 0)
if (fs_pm_open(&file, filename, FS_O_READ) < 0)
{
LOG_ERR("Failed to open %s", filename);
continue;
@@ -284,10 +314,10 @@ void audio_thread(void *arg1, void *arg2, void *arg3)
}
}
fs_close(&file);
fs_pm_flash_suspend();
fs_pm_close(&file);
if (k_msgq_num_used_get(&audio_play_msgq) == 0)
{
i2s_suspend();
io_status(false);
}
@@ -325,6 +355,19 @@ int audio_init(void)
if (ret < 0)
return ret;
if (!gpio_is_ready_dt(&amp_en_dev)) {
LOG_DBG("Amplifier enable GPIO device not ready");
return -ENODEV;
}
ret = gpio_pin_configure_dt(&amp_en_dev, GPIO_OUTPUT_ACTIVE);
if (ret < 0) {
LOG_ERR("Failed to configure amplifier enable GPIO: %d", ret);
return ret;
}
gpio_pin_configure_dt(&amp_en_dev, 0);
audio_refresh_file_count();
LOG_INF("Audio initialized: %u bits, %u.%03u kHz", config.word_size, config.frame_clk_freq / 1000, config.frame_clk_freq % 1000);
return 0;

View File

@@ -79,16 +79,19 @@ int fs_pm_flash_resume(void)
int fs_pm_open(struct fs_file_t *file, const char *path, fs_mode_t mode)
{
LOG_DBG("PM Opening file '%s' with mode 0x%02x", path, mode);
fs_pm_flash_resume();
int rc = fs_open(file, path, mode);
if (rc == 0)
if (rc < 0)
{
fs_pm_flash_resume();
fs_pm_flash_suspend();
}
return rc;
}
int fs_pm_close(struct fs_file_t *file)
{
LOG_DBG("PM Closing file");
int rc = fs_close(file);
if (rc == 0)
{
@@ -99,20 +102,44 @@ int fs_pm_close(struct fs_file_t *file)
int fs_pm_opendir(struct fs_dir_t *dirp, const char *path)
{
LOG_DBG("PM Opening directory '%s'", path);
fs_pm_flash_resume();
int rc = fs_opendir(dirp, path);
if (rc == 0)
if (rc < 0)
{
fs_pm_flash_resume();
fs_pm_flash_suspend();
}
return rc;
}
int fs_pm_closedir(struct fs_dir_t *dirp)
{
LOG_DBG("PM Closing directory");
int rc = fs_closedir(dirp);
if (rc == 0)
{
fs_pm_flash_suspend();
}
return rc;
}
int fs_pm_unlink(const char *path)
{
LOG_DBG("PM Unlinking file '%s'", path);
fs_pm_flash_resume();
int rc = fs_unlink(path);
if (rc < 0)
{
fs_pm_flash_suspend();
}
return rc;
}
int fs_pm_statvfs(const char *path, struct fs_statvfs *stat)
{
LOG_DBG("PM Getting filesystem stats for '%s'", path);
fs_pm_flash_resume();
int rc = fs_statvfs(path, stat);
fs_pm_flash_suspend();
return rc;
}

View File

@@ -18,9 +18,54 @@ int fs_pm_flash_suspend(void);
*/
int fs_pm_flash_resume(void);
/**
* @brief Wrapper around fs_open that handles power management for the flash
* Resumes the flash before opening and suspends it if opening fails
* @param file Pointer to fs_file_t structure to be initialized
* @param path Path to the file to open
* @param mode Open flags (e.g. FS_O_READ, FS_O_WRITE)
* @return 0 on success, negative error code on failure
*/
int fs_pm_open(struct fs_file_t *file, const char *path, fs_mode_t mode);
/**
* @brief Wrapper around fs_close that handles power management for the flash
* Resumes the flash after closing and suspends it if closing fails
* @param file Pointer to fs_file_t structure to be closed
* @return 0 on success, negative error code on failure
*/
int fs_pm_close(struct fs_file_t *file);
/**
* @brief Wrapper around fs_opendir that handles power management for the flash
* Resumes the flash before opening and suspends it if opening fails
* @param dirp Pointer to fs_dir_t structure to be initialized
* @param path Path to the directory to open
* @return 0 on success, negative error code on failure
*/
int fs_pm_opendir(struct fs_dir_t *dirp, const char *path);
/**
* @brief Wrapper around fs_closedir that handles power management for the flash
* Resumes the flash after closing and suspends it if closing fails
* @param dirp Pointer to fs_dir_t structure to be closed
* @return 0 on success, negative error code on failure
*/
int fs_pm_closedir(struct fs_dir_t *dirp);
/**
* @brief Unlinks (deletes) a file, ensuring the flash is active during the operation
* @param path Path to the file to unlink
* @return 0 on success, negative error code on failure
*/
int fs_pm_unlink(const char *path);
/**
* @brief Wrapper around fs_statvfs that handles power management for the flash
* Resumes the flash before getting stats and suspends it afterwards
* @param path Path to the filesystem to get stats for
* @param stat Pointer to fs_statvfs structure to be filled with stats
* @return 0 on success, negative error code on failure
*/
int fs_pm_statvfs(const char *path, struct fs_statvfs *stat);
#endif // FS_H

View File

@@ -66,7 +66,7 @@ int send_info()
{
char info[112];
struct fs_statvfs stat;
int rc = fs_statvfs("/lfs", &stat);
int rc = fs_pm_statvfs("/lfs", &stat);
if (rc)
{
LOG_ERR("Failed to get filesystem stats: %d", rc);
@@ -87,7 +87,7 @@ int put_binary_file(const char *filename, ssize_t filesize, uint32_t expected_cr
size_t accumulated = 0;
fs_file_t_init(&file);
fs_unlink(filename);
fs_pm_unlink(filename);
LOG_DBG("Opening file '%s' for writing (expected size: %zd bytes, expected CRC32: 0x%08x)", filename, filesize, expected_crc32);
rc = fs_pm_open(&file, filename, FS_O_CREATE | FS_O_WRITE);
if (rc < 0)