This commit is contained in:
2026-02-27 11:50:27 +01:00
parent 5934bba4af
commit 82b535a183
12 changed files with 323 additions and 65 deletions

View File

@@ -1,5 +1,5 @@
VERSION_MAJOR = 0
VERSION_MINOR = 0
PATCHLEVEL = 2
PATCHLEVEL = 9
VERSION_TWEAK = 0
EXTRAVERSION = 0

View File

@@ -1,2 +1,6 @@
CONFIG_NRFX_POWER=y
CONFIG_BT=n
CONFIG_NCS_APPLICATION_BOOT_BANNER_STRING="Edi's Buzzer"
# --- Für PRODUKTIONSBUILD: Alle Debug-Features aus ---
# CONFIG_NCS_BOOT_BANNER=n

View File

@@ -63,7 +63,6 @@
pinctrl-names = "default", "sleep";
};
// &uart0 { status = "disabled"; };
&i2c0 { status = "disabled"; };
&spi1 { status = "disabled"; };
&spi3 { status = "disabled"; };
@@ -75,3 +74,14 @@
&ieee802154 { status = "disabled"; };
&bt_hci_sdc { status = "disabled"; };
&cryptocell { status = "disabled"; };
// unkommentieren für prod
// &uart0 { status = "disabled"; };
// / {
// chosen {
// /delete-property/ zephyr,console;
// /delete-property/ zephyr,shell-uart;
// /delete-property/ zephyr,uart-mcumgr;
// /delete-property/ zephyr,ieee802154;
// };
// };

View File

@@ -1,3 +1,28 @@
mcuboot:
address: 0x0
size: 0xC000
region: flash_primary
mcuboot_primary:
address: 0xC000
size: 0x25000
region: flash_primary
mcuboot_pad:
address: 0xC000
size: 0x200
region: flash_primary
app:
address: 0xC200
size: 0x24E00
region: flash_primary
mcuboot_secondary:
address: 0x31000
size: 0x25000
region: flash_primary
littlefs_storage:
address: 0x0
size: 0x800000

View File

@@ -19,6 +19,7 @@ CONFIG_FS_LITTLEFS_PROG_SIZE=256
CONFIG_FS_LITTLEFS_CACHE_SIZE=512
CONFIG_FS_LITTLEFS_LOOKAHEAD_SIZE=128
CONFIG_FS_LITTLEFS_BLOCK_CYCLES=512
CONFIG_MAIN_STACK_SIZE=2048
# --- USB Device & CDC ACM ---
CONFIG_USB_DEVICE_STACK=y
@@ -40,12 +41,39 @@ CONFIG_UART_LINE_CTRL=y
CONFIG_I2S=y
CONFIG_NRFX_I2S=y
# --- Random & HW Info (für Audio-File-Auswahl) ---
# --- MCUMGR für Firmware-Updates ---
CONFIG_REBOOT=y
CONFIG_FLASH_MAP=y
CONFIG_STREAM_FLASH=y
CONFIG_IMG_MANAGER=y
CONFIG_MCUBOOT_IMG_MANAGER=y
# --- HWINFO und CRC ---
CONFIG_HWINFO=y
CONFIG_CRC=y
# --- Debugging & Sicherheit ---
CONFIG_ASSERT=y
CONFIG_HW_STACK_PROTECTION=y
CONFIG_RESET_ON_FATAL_ERROR=y
# --- Unbenutze Features ---
CONFIG_ADC=n
CONFIG_I2C=n
CONFIG_SPI=n
CONFIG_PWM=n
# UNKOMMENTIEREN FÜR PRODUKTIONSBUILD (KEINE KONSOLE, KEIN LOGGING, KEINE DEBUGGING-INFO)
# # --- Konsole & Output komplett aus ---
# CONFIG_CONSOLE=n
# CONFIG_UART_CONSOLE=n
# CONFIG_PRINTK=n
# CONFIG_BOOT_BANNER=n
# CONFIG_STDOUT_CONSOLE=n
# # --- Logging aus ---
# CONFIG_LOG=n
# # --- Debugging-Features reduzieren ---
# CONFIG_ASSERT=n
# CONFIG_DEBUG_THREAD_INFO=n

View File

@@ -10,7 +10,7 @@
#include <fs.h>
#include <io.h>
LOG_MODULE_REGISTER(audio, LOG_LEVEL_DBG);
LOG_MODULE_REGISTER(audio, LOG_LEVEL_INF);
/* Dauer eines Blocks in ms (4096 Bytes / (16kHz * 2 Kanäle * 2 Bytes)) = 64 ms */
#define BLOCK_DURATION_MS 64
@@ -68,8 +68,8 @@ void i2s_resume(void)
void audio_refresh_file_count(void)
{
struct fs_dir_t dirp;
struct fs_dirent entry;
static struct fs_dir_t dirp;
static struct fs_dirent entry;
uint32_t count = 0;
fs_dir_t_init(&dirp);

View File

@@ -1,10 +1,13 @@
#include <zephyr/fs/littlefs.h>
#include <zephyr/drivers/flash.h>
#include <zephyr/dfu/flash_img.h>
#include <zephyr/pm/device.h>
#include <fs.h>
LOG_MODULE_REGISTER(buzz_fs, LOG_LEVEL_DBG);
LOG_MODULE_REGISTER(buzz_fs, LOG_LEVEL_INF);
#define STORAGE_PARTITION_ID FIXED_PARTITION_ID(littlefs_storage)
#define SLOT1_ID FIXED_PARTITION_ID(slot1_partition)
FS_LITTLEFS_DECLARE_DEFAULT_CONFIG(fs_storage_data);
#define QSPI_FLASH_NODE DT_ALIAS(qspi_flash)
@@ -13,8 +16,11 @@ FS_LITTLEFS_DECLARE_DEFAULT_CONFIG(fs_storage_data);
#endif
static const struct device *flash_dev = DEVICE_DT_GET(QSPI_FLASH_NODE);
static volatile uint32_t open_count = 0;
static struct k_mutex flash_pm_lock;
static struct slot_info_t slot1_info;
static struct flash_img_context flash_ctx;
static struct fs_mount_t fs_storage_mnt = {
.type = FS_LITTLEFS,
@@ -30,6 +36,17 @@ int fs_init(void) {
return rc;
}
k_mutex_init(&flash_pm_lock);
const struct flash_area *fa;
rc = flash_area_open(SLOT1_ID, &fa);
if (rc < 0) {
LOG_ERR("Error opening flash area for slot 1: %d", rc);
return rc;
}
slot1_info.start_addr = fa->fa_off;
slot1_info.size = fa->fa_size;
flash_area_close(fa);
LOG_DBG("Filesystem mounted successfully");
return 0;
}
@@ -128,10 +145,7 @@ 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();
}
fs_pm_flash_suspend();
return rc;
}
@@ -143,3 +157,41 @@ int fs_pm_statvfs(const char *path, struct fs_statvfs *stat)
fs_pm_flash_suspend();
return rc;
}
int fs_pm_mkdir(const char *path)
{
LOG_DBG("PM Creating directory '%s'", path);
fs_pm_flash_resume();
int rc = fs_mkdir(path);
fs_pm_flash_suspend();
return rc;
}
int flash_get_slot_info(slot_info_t *info) {
if (slot1_info.size != 0) {
*info = slot1_info;
return 0;
}
return -ENODEV;
}
int flash_init_firmware_upload(void) {
int rc;
rc = flash_img_init_id(&flash_ctx, SLOT1_ID);
if (rc != 0) {
printk("Error initializing flash image: %d\n", rc);
return rc;
}
return 0;
}
int flash_write_firmware_block(const uint8_t *buffer, size_t length, bool is_last_block) {
int rc;
rc = flash_img_buffered_write(&flash_ctx, buffer, length, is_last_block);
if (rc != 0) {
printk("Error writing flash image: %d\n", rc);
return rc;
}
return 0;
}

View File

@@ -3,6 +3,11 @@
#include <zephyr/fs/fs.h>
typedef struct slot_info_t {
size_t start_addr;
size_t size;
} slot_info_t;
/**
* @brief Initializes the filesystem by mounting it
*/
@@ -68,4 +73,35 @@ int fs_pm_unlink(const char *path);
* @return 0 on success, negative error code on failure
*/
int fs_pm_statvfs(const char *path, struct fs_statvfs *stat);
/**
* @brief Wrapper around fs_mkdir that handles power management for the flash
* Resumes the flash before creating the directory and suspends it afterwards
* @param path Path to the directory to create
* @return 0 on success, negative error code on failure
*/
int fs_pm_mkdir(const char *path);
/**
* @brief Retrieves information about the firmware slot, such as start address and size
* @param info Pointer to slot_info_t structure to be filled with slot information
* @return 0 on success, negative error code on failure
*/
int flash_get_slot_info(slot_info_t *info);
/**
* @brief Initializes the flash for firmware upload, preparing it for receiving new firmware data
* @return 0 on success, negative error code on failure
*/
int flash_init_firmware_upload(void);
/**
* @brief Writes a block of firmware data to the flash
* @param buffer Pointer to the data buffer
* @param length Length of the data buffer
* @param is_last_block Indicates if this is the last block of the firmware
* @return 0 on success, negative error code on failure
*/
int flash_write_firmware_block(const uint8_t *buffer, size_t length, bool is_last_block);
#endif // FS_H

View File

@@ -3,7 +3,7 @@
#include <zephyr/drivers/gpio.h>
#include <audio.h>
LOG_MODULE_REGISTER(io, LOG_LEVEL_DBG);
LOG_MODULE_REGISTER(io, LOG_LEVEL_INF);
#define STATUS_LED_NODE DT_ALIAS(status_led)
#define USB_LED_NODE DT_ALIAS(usb_led)

View File

@@ -16,36 +16,9 @@
LOG_MODULE_REGISTER(main, LOG_LEVEL_INF);
void print_device_id(void) {
uint8_t device_id[8]; // 64 Bit = 8 Bytes
ssize_t length;
// Device ID auslesen
length = hwinfo_get_device_id(device_id, sizeof(device_id));
if (length > 0) {
char id_str[17]; // 16 Zeichen + Null-Terminator
for (int i = 0; i < length; i++) {
sprintf(&id_str[i * 2], "%02x", device_id[i]);
}
LOG_INF("Board Device ID: %s", id_str);
} else {
LOG_ERR("Konnte Device ID nicht lesen");
}
}
static int print_custom_banner(void)
{
printk("*** Edis Buzzer Version: " APP_VERSION_STRING " ***" );
return 0;
}
SYS_INIT(print_custom_banner, PRE_KERNEL_1, 0);
int main(void)
{
LOG_INF("Starting Edis Buzzer Application");
print_device_id();
LOG_INF("Starting Edi's Buzzer Application");
int rc;
@@ -75,4 +48,10 @@ int main(void)
LOG_INF("All subsystems initialized. Starting application threads.");
audio_system_ready();
k_sleep(K_SECONDS(5)); // Kurze Pause, damit die READY-Antworten der Subsysteme noch rausgehen
volatile uint32_t *invalid_pointer = (volatile uint32_t *)0xFFFFFFFF;
*invalid_pointer = 0xDEADBEEF;
while (1) {
k_sleep(K_FOREVER);
}
}

View File

@@ -1,9 +1,12 @@
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <zephyr/logging/log_ctrl.h>
#include <string.h>
#include <fs.h>
#include <app_version.h>
#include <zephyr/sys/crc.h>
#include <zephyr/dfu/mcuboot.h>
#include <zephyr/sys/reboot.h>
#include <usb.h>
#include <protocol.h>
@@ -80,22 +83,50 @@ int send_info()
int put_binary_file(const char *filename, ssize_t filesize, uint32_t expected_crc32)
{
int rc;
struct fs_file_t file;
ssize_t bytes_written = 0;
uint32_t running_crc32 = 0;
uint32_t retry_count = 0;
size_t accumulated = 0;
struct fs_file_t file;
bool firmware_update = false;
fs_file_t_init(&file);
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)
if (strcmp(filename, "update.bin") == 0 ||
strcmp(filename, "firmware.bin") == 0 ||
strcmp(filename, "update") == 0 ||
strcmp(filename, "firmware") == 0)
{
LOG_ERR("Failed to open file '%s' for writing: %d", filename, rc);
return -rc;
firmware_update = true;
LOG_INF("Firmware update requested with file '%s'", filename);
}
if (firmware_update)
{
slot_info_t slot1_info;
rc = flash_get_slot_info(&slot1_info);
if (rc < 0)
{
LOG_ERR("Failed to get slot 1 info: %d", rc);
return rc;
}
if (filesize > slot1_info.size)
{
LOG_ERR("File size %zd exceeds slot 1 size %zu", filesize, slot1_info.size);
return -EFBIG;
}
flash_init_firmware_upload();
}
else
{
fs_file_t_init(&file);
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)
{
LOG_ERR("Failed to open file '%s' for writing: %d", filename, rc);
return -rc;
}
}
usb_write_buffer((const uint8_t *)"READY\n", 6);
uint32_t start = k_uptime_get_32();
@@ -110,7 +141,13 @@ int put_binary_file(const char *filename, ssize_t filesize, uint32_t expected_cr
if (read < 0)
{
LOG_ERR("Error reading from USB: %d", read);
fs_pm_close(&file);
if (firmware_update)
{
}
else
{
fs_pm_close(&file);
}
return -read;
}
else if (read == 0)
@@ -118,18 +155,24 @@ int put_binary_file(const char *filename, ssize_t filesize, uint32_t expected_cr
if (retry_count >= 10)
{
LOG_ERR("No data received from USB after multiple attempts");
fs_pm_close(&file);
if (firmware_update)
{
}
else
{
fs_pm_close(&file);
}
return -ETIMEDOUT;
}
usb_resume_rx();
if ((bytes_written + accumulated) == 0)
{
usb_wait_for_data(K_SECONDS(30));
usb_wait_for_data(K_SECONDS(1));
}
else
{
usb_wait_for_data(K_SECONDS(1));
usb_wait_for_data(K_MSEC(100));
}
retry_count++;
continue;
@@ -144,14 +187,25 @@ int put_binary_file(const char *filename, ssize_t filesize, uint32_t expected_cr
ODER wenn wir das Ende der Datei erreicht haben. */
if (accumulated == sizeof(buffer) || (bytes_written + accumulated) == filesize)
{
ssize_t written = fs_write(&file, buffer, accumulated);
if (written < 0)
if (firmware_update)
{
LOG_ERR("Error writing to file '%s': %d", filename, (int)written);
fs_pm_close(&file);
return (int)written;
int rc = flash_write_firmware_block(buffer, accumulated, (bytes_written + accumulated) == filesize);
if (rc < 0)
{
LOG_ERR("Error writing to flash: %d", rc);
return rc;
}
}
else
{
ssize_t written = fs_write(&file, buffer, accumulated);
if (written < 0)
{
LOG_ERR("Error writing to file '%s': %d", filename, (int)written);
fs_pm_close(&file);
return (int)written;
}
}
/* CRC erst nach dem erfolgreichen Block-Schreiben berechnen */
running_crc32 = crc32_ieee_update(running_crc32, buffer, accumulated);
bytes_written += accumulated;
@@ -164,8 +218,26 @@ int put_binary_file(const char *filename, ssize_t filesize, uint32_t expected_cr
uint32_t duration = k_uptime_get_32() - start;
uint32_t kb_per_s = (filesize * 1000) / (duration * 1024 + 1);
LOG_DBG("Received file '%s' (%zd bytes) in %u ms (%u kb/s), CRC32: 0x%08x", filename, filesize, duration, kb_per_s, running_crc32);
fs_pm_close(&file);
LOG_DBG("Closed file '%s' after writing", filename);
if (firmware_update)
{
int rc;
rc = boot_request_upgrade(BOOT_UPGRADE_TEST);
if (rc < 0) {
LOG_ERR("Failed to request firmware upgrade: %d", rc);
return rc;
}
send_ok();
LOG_INF("Firmware upgrade requested, rebooting into bootloader...");
k_sleep(K_MSEC(100)); // Kurze Pause, damit die OK-Antwort noch rausgeht
while (log_process());
sys_reboot(SYS_REBOOT_COLD);
}
else
{
fs_pm_close(&file);
LOG_DBG("Closed file '%s' after writing", filename);
}
if (running_crc32 != expected_crc32)
{
LOG_ERR("CRC32 mismatch for file '%s': expected 0x%08x, got 0x%08x", filename, expected_crc32, running_crc32);
@@ -175,6 +247,26 @@ int put_binary_file(const char *filename, ssize_t filesize, uint32_t expected_cr
return 0;
}
int mkdir(const char *path) {
int rc = fs_pm_mkdir(path);
if (rc < 0)
{
LOG_ERR("Failed to create directory '%s': %d", path, rc);
}
LOG_DBG("Directory '%s' created successfully", path);
return rc;
}
int rm(const char *path) {
int rc = fs_pm_unlink(path);
if (rc < 0)
{
LOG_ERR("Failed to remove '%s': %d", path, rc);
}
LOG_DBG("'%s' removed successfully", path);
return rc;
}
void execute_current_command(void)
{
int rc;
@@ -233,6 +325,27 @@ void execute_current_command(void)
send_error(rc);
}
break;
case CMD_MKDIR:
LOG_DBG("Executing MKDIR command with parameters: '%s'", buffer);
rc = mkdir((char *)buffer);
if (rc == 0) {
send_ok();
}
else {
send_error(rc);
}
break;
case CMD_RM:
LOG_DBG("Executing RM command with parameters: '%s'", buffer);
rc = rm((char *)buffer);
if (rc == 0) {
send_ok();
audio_refresh_file_count(); // Nach erfolgreichem Löschen die Anzahl der verfügbaren Audiodateien aktualisieren
}
else {
send_error(rc);
}
break;
default:
LOG_ERR("No execution logic for command %d", current_command);
send_error(ENOSYS);
@@ -274,7 +387,16 @@ protocol_state_t reading_command(uint8_t byte)
LOG_DBG("Received PUT_BINARY_FILE command");
current_command = CMD_PUT_BINARY_FILE;
}
else if (strcmp((char *)buffer, "mkdir") == 0)
{
LOG_DBG("Received MKDIR command");
current_command = CMD_MKDIR;
}
else if (strcmp((char *)buffer, "rm") == 0)
{
LOG_DBG("Received RM command");
current_command = CMD_RM;
}
else
{
LOG_DBG("Unknown command: %s", buffer);

View File

@@ -13,6 +13,8 @@ typedef enum {
CMD_INFO,
CMD_LS,
CMD_PUT_BINARY_FILE,
CMD_MKDIR,
CMD_RM,
/* Weitere Kommandos folgen hier */
} protocol_cmd_t;