Hello Nordic Support,
I have modified the USB MSC example to use SD card and have also initialized UART port. Basically, what I'm trying to achieve is to write data received over UART in SD card and the SD card contents must show up when plugged via USB.
Without the UART initialized, I can see the LEDs turn ON and the SD card contents on Windows PC via nrf52840 USB port. However, if I initialize the UART, I no longer see the LEDs ON and the USB port no longer appears on Windows PC.
Can you please provide your inputs on the possible cause for this?
I've attached the program used. To reproduce the issue, just un comment the function "uart_init()" in main().
/** * Copyright (c) 2016 - 2019, Nordic Semiconductor ASA * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * 2. Redistributions in binary form, except as embedded into a Nordic * Semiconductor ASA integrated circuit in a product or a software update for * such product, must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. Neither the name of Nordic Semiconductor ASA nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * 4. This software, with or without modification, must only be used with a * Nordic Semiconductor ASA integrated circuit. * * 5. Any software provided in binary form under this license must not be reverse * engineered, decompiled, modified and/or disassembled. * * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /** @file * @defgroup fatfs_example_main main.c * @{ * @ingroup fatfs_example * @brief FATFS Example Application main file. * * This file contains the source code for a sample application using FAT filesystem and SD card library. * */ #include <stdbool.h> #include <stdint.h> #include <stddef.h> #include "nrf.h" #include "bsp.h" #include "ff.h" #include "diskio_blkdev.h" #include "nrf_block_dev_sdc.h" #include "app_uart.h" #include "nrf_uart.h" #include "nrf_drv_clock.h" #include "nrf_gpio.h" #include "nrf_delay.h" #include "nrf_drv_power.h" #include "nrf_serial.h" #include "app_timer.h" #include "app_usbd.h" #include "app_usbd_core.h" #include "app_usbd_string_desc.h" #include "app_usbd_msc.h" #include "app_error.h" #include "app_util.h" #include "nrf_log.h" #include "nrf_log_ctrl.h" #include "nrf_log_default_backends.h" #define FILE_NAME "NORDIC.TXT" #define TEST_STRING "SD card example." #define SDC_SCK_PIN ARDUINO_13_PIN ///< SDC serial clock (SCK) pin. #define SDC_MOSI_PIN ARDUINO_11_PIN ///< SDC serial data in (DI) pin. #define SDC_MISO_PIN ARDUINO_12_PIN ///< SDC serial data out (DO) pin. #define SDC_CS_PIN ARDUINO_10_PIN ///< SDC chip select (CS) pin. #define OP_QUEUES_SIZE 3 #define APP_TIMER_PRESCALER NRF_SERIAL_APP_TIMER_PRESCALER #define UART_TX_BUF_SIZE 256 /**< UART TX buffer size. */ #define UART_RX_BUF_SIZE 256 /**< UART RX buffer size. */ static void sleep_handler(void) { __WFE(); __SEV(); __WFE(); } typedef struct { uint8_t * p_data; uint32_t length; } buffer_t; /** * @brief SDC block device definition * */ NRF_BLOCK_DEV_SDC_DEFINE( m_block_dev_sdc, NRF_BLOCK_DEV_SDC_CONFIG( SDC_SECTOR_SIZE, APP_SDCARD_CONFIG(SDC_MOSI_PIN, SDC_MISO_PIN, SDC_SCK_PIN, SDC_CS_PIN) ), NFR_BLOCK_DEV_INFO_CONFIG("Nordic", "SDC", "1.00") ); #define LED_USB_RESUME (BSP_BOARD_LED_0) #define LED_USB_START (BSP_BOARD_LED_1) /** * @brief Enable power USB detection * * Configure if example supports USB port connection */ #ifndef USBD_POWER_DETECTION #define USBD_POWER_DETECTION true #endif /** * @brief Mass storage class user event handler */ static void msc_user_ev_handler(app_usbd_class_inst_t const * p_inst, app_usbd_msc_user_event_t event); /** * @brief Ram block device size * * @note Windows fails to format volumes smaller than 190KB */ #define RAM_BLOCK_DEVICE_SIZE (380 * 512) #define BLOCKDEV_LIST() ( \ NRF_BLOCKDEV_BASE_ADDR(m_block_dev_sdc, block_dev) \ ) /** * @brief Endpoint list passed to @ref APP_USBD_MSC_GLOBAL_DEF */ #define ENDPOINT_LIST() APP_USBD_MSC_ENDPOINT_LIST(1, 1) /** * @brief Mass storage class work buffer size */ #define MSC_WORKBUFFER_SIZE (1024) /*lint -save -e26 -e64 -e123 -e505 -e651*/ /** * @brief Mass storage class instance */ APP_USBD_MSC_GLOBAL_DEF(m_app_msc, 0, msc_user_ev_handler, ENDPOINT_LIST(), BLOCKDEV_LIST(), MSC_WORKBUFFER_SIZE); /** * @brief USB connection status */ static bool m_usb_connected = false; /** * @brief Class specific event handler. * * @param p_inst Class instance. * @param event Class specific event. */ static void msc_user_ev_handler(app_usbd_class_inst_t const * p_inst, app_usbd_msc_user_event_t event) { UNUSED_PARAMETER(p_inst); UNUSED_PARAMETER(event); } /** * @brief Ram block device size * * @note Windows fails to format volumes smaller than 190KB */ #define RAM_BLOCK_DEVICE_SIZE (380 * 512) /** * @brief RAM block device work buffer */ static uint8_t m_block_dev_ram_buff[RAM_BLOCK_DEVICE_SIZE]; static void fatfs_init() { static FATFS fs; static DIR dir; static FILINFO fno; FRESULT ff_result; DSTATUS disk_state = STA_NOINIT; // Initialize FATFS disk I/O interface by providing the block device. static diskio_blkdev_t drives[] = { DISKIO_BLOCKDEV_CONFIG(NRF_BLOCKDEV_BASE_ADDR(m_block_dev_sdc, block_dev), NULL) }; diskio_blockdev_register(drives, ARRAY_SIZE(drives)); // Initializing disk 0 (SDC) for (uint32_t retries = 3; retries && disk_state; --retries) { disk_state = disk_initialize(0); } if (disk_state) // Disk initialization failed { return; } uint32_t blocks_per_mb = (1024uL * 1024uL) / m_block_dev_sdc.block_dev.p_ops->geometry(&m_block_dev_sdc.block_dev)->blk_size; uint32_t capacity = m_block_dev_sdc.block_dev.p_ops->geometry(&m_block_dev_sdc.block_dev)->blk_count / blocks_per_mb; //Get the SD card capacity // Mounting volume ff_result = f_mount(&fs, "", 1); if (ff_result) // Mount failed { return; } // Listing directory ff_result = f_opendir(&dir, "/"); if (ff_result) // Directory listing failed { return; } do { ff_result = f_readdir(&dir, &fno); if (ff_result != FR_OK) // Directory read failed { return; } } while (fno.fname[0]); } static void fatfs_uninit(void) { NRF_LOG_INFO("Un-initializing disk 0 (SD card)..."); UNUSED_RETURN_VALUE(disk_uninitialize(0)); } /** * @brief USBD library specific event handler. * * @param event USBD library event. */ static void usbd_user_ev_handler(app_usbd_event_type_t event) { switch (event) { case APP_USBD_EVT_DRV_SUSPEND: bsp_board_led_off(LED_USB_RESUME); break; case APP_USBD_EVT_DRV_RESUME: bsp_board_led_on(LED_USB_RESUME); break; case APP_USBD_EVT_STARTED: bsp_board_led_on(LED_USB_START); break; case APP_USBD_EVT_STOPPED: UNUSED_RETURN_VALUE(fatfs_init()); app_usbd_disable(); bsp_board_leds_off(); break; case APP_USBD_EVT_POWER_DETECTED: NRF_LOG_INFO("USB power detected"); if (!nrf_drv_usbd_is_enabled()) { fatfs_uninit(); app_usbd_enable(); } break; case APP_USBD_EVT_POWER_REMOVED: NRF_LOG_INFO("USB power removed"); app_usbd_stop(); m_usb_connected = false; break; case APP_USBD_EVT_POWER_READY: NRF_LOG_INFO("USB ready"); app_usbd_start(); m_usb_connected = true; break; default: break; } } static void fatfs_write(const void * buff, const void * fileName, uint32_t len) { FIL file; FRESULT ff_result; uint32_t bytes_written = 0; ff_result = f_open(&file, fileName, FA_READ | FA_WRITE | FA_OPEN_APPEND); if (ff_result != FR_OK) { return; } ff_result = f_write(&file, buff, len - 1, (UINT *) &bytes_written); if (ff_result != FR_OK) { return; } (void) f_close(&file); return; } static int32_t fatfs_read(void * buff, const void * fileName, uint32_t len, uint32_t offset) { FIL file; FRESULT ff_result; uint32_t bytes_read = 0; ff_result = f_open(&file, fileName, FA_READ); if (ff_result != FR_OK) { return -1; } ff_result = f_lseek(&file, offset); if (ff_result != FR_OK) { return -1; } ff_result = f_read(&file, buff, len, &bytes_read); if (ff_result != FR_OK) { return -1; } (void) f_close(&file); return (int32_t)bytes_read; } /**@snippet [UART Initialization] */ /**@brief Function for handling app_uart events. * * @details This function will receive a single character from the app_uart module and append it to * a string. The string will be be sent over BLE when the last character received was a * 'new line' '\n' (hex 0x0A) or if the string has reached the maximum data length. */ /**@snippet [Handling the data received over UART] */ void uart_event_handle(app_uart_evt_t * p_event) { static uint8_t data_array[113]; static uint8_t index = 0; uint8_t readData[113]; uint32_t err_code; static uint32_t offset = 0; switch (p_event->evt_type) { case APP_UART_DATA_READY: UNUSED_VARIABLE(app_uart_get(&data_array[index])); index++; if (data_array[index-1] == '\n') { fatfs_write(data_array, "NSData.bin", index); index = 0; } break; case APP_UART_COMMUNICATION_ERROR: APP_ERROR_HANDLER(p_event->data.error_communication); break; case APP_UART_FIFO_ERROR: APP_ERROR_HANDLER(p_event->data.error_code); break; //case APP_UART_TX_EMPTY: //nrf_gpio_pin_clear(17); //tx_empty_flag = false; //break; default: break; } } /**@snippet [Handling the data received over UART] */ /**@brief Function for initializing the UART module. */ /**@snippet [UART Initialization] */ static void uart_init(void) { uint32_t err_code; app_uart_comm_params_t const comm_params = { .rx_pin_no = ARDUINO_SDA_PIN, .tx_pin_no = ARDUINO_SCL_PIN, .rts_pin_no = UART_PIN_DISCONNECTED, .cts_pin_no = UART_PIN_DISCONNECTED, .flow_control = APP_UART_FLOW_CONTROL_DISABLED, .use_parity = false, .baud_rate = NRF_UART_BAUDRATE_115200 }; APP_UART_FIFO_INIT(&comm_params, UART_RX_BUF_SIZE, UART_TX_BUF_SIZE, uart_event_handle, APP_IRQ_PRIORITY_LOWEST, err_code); APP_ERROR_CHECK(err_code); } /** * @brief Function for main application entry. */ int main(void) { bsp_board_init(BSP_INIT_LEDS); ret_code_t ret; static const app_usbd_config_t usbd_config = { .ev_state_proc = usbd_user_ev_handler }; ret = NRF_LOG_INIT(app_usbd_sof_timestamp_get); APP_ERROR_CHECK(ret); ret = nrf_drv_clock_init(); APP_ERROR_CHECK(ret); /* Fill whole RAM block device buffer */ for (size_t i = 0; i < sizeof(m_block_dev_ram_buff); ++i) { m_block_dev_ram_buff[i] = i; } ret = nrf_drv_power_init(NULL); APP_ERROR_CHECK(ret); nrf_drv_clock_lfclk_request(NULL); ret = app_timer_init(); APP_ERROR_CHECK(ret); fatfs_init(); ret = app_usbd_init(&usbd_config); APP_ERROR_CHECK(ret); app_usbd_class_inst_t const * class_inst_msc = app_usbd_msc_class_inst_get(&m_app_msc); ret = app_usbd_class_append(class_inst_msc); APP_ERROR_CHECK(ret); if (USBD_POWER_DETECTION) { ret = app_usbd_power_events_enable(); APP_ERROR_CHECK(ret); } else { NRF_LOG_INFO("No USB power detection enabled\r\nStarting USB now"); app_usbd_enable(); app_usbd_start(); m_usb_connected = true; } //uart_init(); while (true) { while (app_usbd_event_queue_process()) { /* Nothing to do */ } __WFE(); } } /** @} */