From 33ee830e9cc97cdd260c4909d7d54a54c779b4cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20V=C3=A5rdal?= Date: Wed, 28 Jun 2023 15:43:37 +0200 Subject: [PATCH] applications: nrf5340_audio: Expand SD card module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To avoid unnecessary opening and closing of files and additional functions Signed-off-by: Marius VĂ¥rdal --- .../nrf5340_audio/src/modules/sd_card.c | 154 ++++++++++++++++-- .../nrf5340_audio/src/modules/sd_card.h | 53 +++++- 2 files changed, 194 insertions(+), 13 deletions(-) diff --git a/applications/nrf5340_audio/src/modules/sd_card.c b/applications/nrf5340_audio/src/modules/sd_card.c index f44aa97a7ec9..b0093dc6f1c0 100644 --- a/applications/nrf5340_audio/src/modules/sd_card.c +++ b/applications/nrf5340_audio/src/modules/sd_card.c @@ -24,13 +24,15 @@ LOG_MODULE_REGISTER(sd_card, CONFIG_MODULE_SD_CARD_LOG_LEVEL); static const char *sd_root_path = "/SD:"; static FATFS fat_fs; static bool sd_init_success; +static volatile bool seg_read_started; +static struct fs_file_t f_seg_read_entry; static struct fs_mount_t mnt_pt = { .type = FS_FATFS, .fs_data = &fat_fs, }; -int sd_card_list_files(char *path) +int sd_card_list_files(char *path, char *buf, size_t buf_size) { int ret; struct fs_dir_t dirp; @@ -62,6 +64,8 @@ int sd_card_list_files(char *path) return ret; } } + + size_t used_buf_size = 0; while (true) { ret = fs_readdir(&dirp, &entry); if (ret) { @@ -71,12 +75,19 @@ int sd_card_list_files(char *path) if (entry.name[0] == 0) { break; } - - if (entry.type == FS_DIR_ENTRY_DIR) { - LOG_INF("[DIR ] %s", entry.name); - } else { - LOG_INF("[FILE] %s", entry.name); + if (buf != NULL) { + size_t remaining_buf_size = buf_size - used_buf_size; + ssize_t len = snprintk( + &buf[used_buf_size], remaining_buf_size, "[%s]\t%s\n", + entry.type == FS_DIR_ENTRY_DIR ? "DIR " : "FILE", entry.name); + used_buf_size += len; + + if ((len < 0) || (len >= remaining_buf_size)) { + LOG_ERR("Failed to append to buffer, error: %d", len); + return -EINVAL; + } } + LOG_INF("[%s] %s", entry.type == FS_DIR_ENTRY_DIR ? "DIR " : "FILE", entry.name); } ret = fs_closedir(&dirp); @@ -84,15 +95,14 @@ int sd_card_list_files(char *path) LOG_ERR("Close SD card root dir failed"); return ret; } - return 0; } int sd_card_write(char const *const filename, char const *const data, size_t *size) { + int ret; struct fs_file_t f_entry; char abs_path_name[PATH_MAX_LEN + 1] = SD_ROOT_PATH; - int ret; if (!sd_init_success) { return -ENODEV; @@ -100,7 +110,7 @@ int sd_card_write(char const *const filename, char const *const data, size_t *si if (strlen(filename) > CONFIG_FS_FATFS_MAX_LFN) { LOG_ERR("Filename is too long"); - return -FR_INVALID_NAME; + return -ENAMETOOLONG; } strcat(abs_path_name, filename); @@ -138,9 +148,9 @@ int sd_card_write(char const *const filename, char const *const data, size_t *si int sd_card_read(char const *const filename, char *const data, size_t *size) { + int ret; struct fs_file_t f_entry; char abs_path_name[PATH_MAX_LEN + 1] = SD_ROOT_PATH; - int ret; if (!sd_init_success) { return -ENODEV; @@ -180,6 +190,126 @@ int sd_card_read(char const *const filename, char *const data, size_t *size) return 0; } +int sd_card_segment_open(char const *const filename, char const *const path_to_file) +{ + int ret; + + if (strlen(path_to_file) > PATH_MAX_LEN) { + LOG_ERR("Filepath is too long"); + return -EINVAL; + } + + char abs_path_name[PATH_MAX_LEN + 1] = SD_ROOT_PATH; + strcat(abs_path_name, path_to_file); + LOG_INF("abs path name:\t%s\n", abs_path_name); + + if (!sd_init_success) { + return -ENODEV; + } + + if (strlen(filename) > CONFIG_FS_FATFS_MAX_LFN) { + LOG_ERR("Filename is too long"); + return -ENAMETOOLONG; + } + + strcat(abs_path_name, filename); + fs_file_t_init(&f_seg_read_entry); + + ret = fs_open(&f_seg_read_entry, abs_path_name, FS_O_READ); + if (ret) { + LOG_ERR("Open file failed"); + return ret; + } + + seg_read_started = true; + + return 0; +} + +int sd_card_segment_read(char *const data, size_t *size) +{ + int ret; + + if (!seg_read_started) { + return -EBUSY; + } + + ret = fs_read(&f_seg_read_entry, data, *size); + if (ret < 0) { + LOG_ERR("Read file failed"); + return ret; + } + + *size = ret; + + return 0; +} + +int sd_card_segment_peek(char *const data, size_t *size) +{ + int ret; + + off_t offset; + + if (!seg_read_started) { + return -EBUSY; + } + + offset = fs_tell(&f_seg_read_entry); + if (offset < 0) { + LOG_ERR("Fs tell failed"); + return offset; + } + ret = fs_read(&f_seg_read_entry, data, *size); + if (ret < 0) { + LOG_ERR("Read file failed"); + return ret; + } + ret = fs_seek(&f_seg_read_entry, offset, 0); + if (ret < 0) { + LOG_ERR("Fs seek failed"); + return ret; + } + *size = ret; + + return 0; +} + +int sd_card_segment_skip(const size_t *size) +{ + int ret; + + if (!seg_read_started) { + return -EBUSY; + } + ret = fs_seek(&f_seg_read_entry, *size, FS_SEEK_CUR); + if (ret < 0) { + LOG_ERR("Fs seek failed. Return value: %d\n", ret); + return ret; + } + + return 0; +} + +int sd_card_segment_close(void) +{ + int ret; + + if (!seg_read_started) { + return -EBUSY; + } + + ret = fs_close(&f_seg_read_entry); + if (ret) { + LOG_ERR("Close file failed"); + return ret; + } + + seg_read_started = false; + + return 0; +} + int sd_card_init(void) { int ret; @@ -199,6 +329,7 @@ int sd_card_init(void) LOG_ERR("Unable to get sector count"); return ret; } + LOG_DBG("Sector count: %d", sector_count); ret = disk_access_ioctl(sd_dev, DISK_IOCTL_GET_SECTOR_SIZE, §or_size); @@ -206,12 +337,15 @@ int sd_card_init(void) LOG_ERR("Unable to get sector size"); return ret; } + LOG_DBG("Sector size: %d bytes", sector_size); sd_card_size_bytes = (uint64_t)sector_count * sector_size; + LOG_INF("SD card volume size: %d MB", (uint32_t)(sd_card_size_bytes >> 20)); mnt_pt.mnt_point = sd_root_path; + ret = fs_mount(&mnt_pt); if (ret) { LOG_ERR("Mnt. disk failed, could be format issue. should be FAT/exFAT"); diff --git a/applications/nrf5340_audio/src/modules/sd_card.h b/applications/nrf5340_audio/src/modules/sd_card.h index bf72080e237a..7e28ba5c8dee 100644 --- a/applications/nrf5340_audio/src/modules/sd_card.h +++ b/applications/nrf5340_audio/src/modules/sd_card.h @@ -9,17 +9,19 @@ #include -/**@brief Print out the contents under SD card root path +/**@brief Print out the contents under SD card root path and write the content to buffer. * * @param[in] path Path of the folder which going to list * If assigned path is null, then listing the contents under root * If assigned path doesn't exist, an error will be returned - * + * @param[in, out] buf Buffer where data is written. If set to NULL, it will be ignored. + * @param[in] buf_size Buffer size * @return 0 on success. * -ENODEV SD init failed. SD card likely not inserted + * -EINVAL Failed to append to buffer * Otherwise, error from underlying drivers */ -int sd_card_list_files(char *path); +int sd_card_list_files(char *path, char *buf, size_t buf_size); /**@brief Write data from buffer into the file * @@ -52,6 +54,51 @@ int sd_card_write(char const *const filename, char const *const data, size_t *si */ int sd_card_read(char const *const filename, char *const data, size_t *size); +/**@brief Open file on SD card + * param[in] filename Name of file to open + * param[in] path_to_file Path to file + * @retval 0 on success + * -ENODEV SD init failed. SD likely not inserted + * Otherwise, error from underlying drivers + */ +int sd_card_segment_open(char const *const filename, char const *const path_to_file); + +/**@brief Read segment on the open file on the SD card + * param[in] data Where the read data is stored + * @param[in,out] size Number of bytes to be read from file + * The actual read size will be returned + * If the actual read size is 0, there will be a warning message which + * indicates that the file is empty + * @retval 0 on success + * -ENODEV SD init failed. SD likely not inserted + * Otherwise, error from underlying drivers + */ +int sd_card_segment_read(char *const data, size_t *size); + +/**@brief Close the file opened by the sd_card_segment_read_open function + * @retval 0 on success + * -EBUSY Segment read operation has not started + * Otherwise, error from underlying drivers + */ +int sd_card_segment_close(void); + +/**@brief Peek at data ahead of current file position without changing file position + * param[in, out] data Location to where the read data should be stored + * param[in, out] size Size of data to be read + * @retval 0 on success + * -EBUSY Segment read operation has not started + * Otherwise, error from underlying drivers + */ +int sd_card_segment_peek(char *const data, size_t *size); + +/**@brief Jump over segment from current file position + * param[in] size Size of segment to skip + * @retval 0 on success + * -EBUSY Segment read operation has not started + * Otherwise, error from underlying drivers + */ +int sd_card_segment_skip(const size_t *size); + /**@brief Initialize the SD card interface and print out SD card details. * * @retval 0 on success