//! //! @brief Synchronize the contents of two drives (limited to files). //! //! @param sync_direction uint8_t: DEVICE_TO_HOST, HOST_TO_DEVICE or FULL_SYNC //! //! @return bool: true on success //! //! @todo Do recursive directory copy... //! bool host_mass_storage_task_sync_drives(uint8_t sync_direction) { Fs_index local_index; Fs_index sav_local_index; Fs_index usb_index; Fs_index sav_usb_index; // First, check the host controller is in full operating mode with the // B-device attached and enumerated if (!Is_host_ready()) return false; nav_reset(); // Try to mount local drive nav_drive_set(LUN_ID_AT45DBX_MEM); if (!nav_partition_mount()) return false; local_index = nav_getindex(); sav_local_index = nav_getindex(); // Try to mount first USB device drive nav_drive_set(LUN_ID_MEM_USB); if (!nav_partition_mount()) return false; usb_index = nav_getindex(); sav_usb_index = nav_getindex(); // First synchronization: USB/OUT -> Local/IN if (sync_direction & DEVICE_TO_HOST) { if (!host_mass_storage_task_sync_dir(&local_index, DIR_LOCAL_IN_NAME, &usb_index, DIR_USB_OUT_NAME)) return false; } // Restore positions nav_gotoindex(&sav_local_index); local_index = nav_getindex(); nav_gotoindex(&sav_usb_index); usb_index = nav_getindex(); nav_gotoindex(&local_index); // Second synchronization: Local/OUT -> USB/IN if (sync_direction & HOST_TO_DEVICE) { if (!host_mass_storage_task_sync_dir(&usb_index, DIR_USB_IN_NAME, &local_index, DIR_LOCAL_OUT_NAME)) return false; } return true; }
//! @brief This function mount a drive //! void ushell_cmd_mount( void ) { uint8_t u8_drive_lun; Fs_index sav_index; if( g_s_arg[0][0] == 0 ) return; // Compute the logical unit number of drive u8_drive_lun=g_s_arg[0][0]-'a'; // Check lun number if( u8_drive_lun >= nav_drive_nb() ) { fputs(MSG_ER_DRIVE, stdout); return; } // Mount drive sav_index = nav_getindex(); // Save previous position if( nav_drive_set(u8_drive_lun)) { if( nav_partition_mount() ) return; // Here, drive mounted } fputs(MSG_ER_MOUNT, stdout); nav_gotoindex(&sav_index); // Restore previous position }
//! @brief This function displays the free space of each drive present //! void ushell_cmd_free_space( void ) { uint8_t u8_tmp; Fs_index sav_index = nav_getindex(); // Save current position for( u8_tmp=0; u8_tmp<nav_drive_nb(); u8_tmp++ ) { nav_drive_set( u8_tmp ); // Select drive if( !nav_partition_mount() ) // Mount drive continue; // Display drive letter name (a, b...) printf("%c: %s\r\n", 'a'+u8_tmp, mem_name(u8_tmp) ); if( g_s_arg[0][0]=='l' ) // Choose command option { // Long and exact function printf("Free space: %llu Bytes / %llu Bytes\n\r", (uint64_t)(nav_partition_freespace() << FS_SHIFT_B_TO_SECTOR), (uint64_t)(nav_partition_space() << FS_SHIFT_B_TO_SECTOR)); } else { // Otherwise use fast command printf("Free space: %u %%\n\r", nav_partition_freespace_percent() ); } } nav_gotoindex(&sav_index); // Restore position }
//! This function goes to the beginning of file list //! //! @verbatim //! This routine is not authorized then a play list file is opened //! @endverbatim //! void navauto_mov_explorer_reset( void ) { g_navauto_u16_nb = 0; switch( g_navauto_exp_mode ) { case NAVAUTO_MODE_DISKS : // Go to the root of the first disk g_navauto_u16_dir_level = 0; g_navauto_u16_dir_level_root = 0; nav_drive_set(0); nav_dir_root(); // Ignore error, because this one is managed by routine next file break; case NAVAUTO_MODE_DISK : // Go to the root of the current disk g_navauto_u16_dir_level = 0; g_navauto_u16_dir_level_root = 0; nav_dir_root(); // Ignore error, because this one is managed by routine next file break; default: g_navauto_u16_dir_level = 0; g_navauto_u16_dir_level_root = 0; nav_dir_root(); // nav_filelist_reset(); // Reset directory = no selected file break; } // Here the navigator is at the beginning of file list // and no file is selected g_navauto_u16_pos = (uint16_t) -1; }
//! This function selects a file in the navigator via a file index //! //! @param index structure with information about file to select (disk, partition, dir, file/dir selected ) //! //! @return false in case of error, see global value "fs_g_status" for more detail //! @return true otherwise //! //! @verbatim //! This routine allow to reinit a navigator quickly via a file index (disk, partition, dir, file/dir selected ) //! To get a file index, you shall used the routine nav_getindex(). //! @endverbatim //! bool nav_filterlist_gotoindex( const Fs_index _MEM_TYPE_SLOW_ *index ) { if( !nav_drive_set( index->u8_lun )) return false; #if (FS_MULTI_PARTITION == true) if( !nav_partition_set(index->u8_partition)) return false; #endif if( !nav_partition_mount()) return false; // Initialization of the current entry file with index information fs_g_nav.u32_cluster_sel_dir = index->u32_cluster_sel_dir; // Reset position if ( !nav_filterlist_reset() ) return false; // Research the index in directory while( fs_g_nav_fast.u16_entry_pos_sel_file != index->u16_entry_pos_sel_file ) { if( !nav_filterlist_next() ) { nav_filterlist_reset(); return false; } } return true; }
static __inline__ uint8_t navauto_mov_ok_loop(bool b_direction, navauto_mov_options_t options) { bool b_ok_loop = false; // If mode Disks, it should go to the next/previous disk if (g_navauto_exp_mode == NAVAUTO_MODE_DISKS) { // Mount the next/previous disk do { if (b_direction == FS_FIND_NEXT) { // Go to the next drive if (!nav_drive_set(nav_drive_get() + 1)) { nav_drive_set(0); b_ok_loop = true; } } else // direction PREVIOUS { // Go to the previous drive if (!nav_drive_set(nav_drive_get() - 1)) { nav_drive_set(nav_drive_nb() - 1); b_ok_loop = true; } } }while(!nav_partition_mount()); // If it reached a limit if (b_ok_loop) { navauto_mov_explorer_rec(b_direction, options); return NAVAUTO_MOV_OK_LOOP; } // Else return the result of the recursive function return navauto_mov_explorer_rec(b_direction, options); } return NAVAUTO_MOV_OK_LOOP; }
//! @brief This function formats a drive //! void ushell_cmd_format( void ) { if( g_s_arg[0][0] == 0 ) return; // Select drive to format nav_drive_set( g_s_arg[0][0]-'a'); if( !nav_drive_format(FS_FORMAT_DEFAULT) ) { fputs(MSG_ER_FORMAT, stdout); return; } }
static bool ai_sd_mmc_nav_drive_set(uint8_t n, ai_async_status_t *status) { extern void ai_usb_ms_init_drive(void); bool s; *status = CMD_DONE; // Notify the audio interface layer that a new connection is performed ai_usb_ms_new_connection(); ai_usb_ms_init_drive(); s = nav_drive_set(LUN_ID_2); if (!s) { *status = CMD_ERROR; return false; } return true; }
void msc_comm_init(void) { // b_fsaccess_init(); const uint8_t _MEM_TYPE_SLOW_ script_name[17] = {'.', 'c', 'e', 'l', 'l', 'a', '_', 'u', 'n', 'l', 'o', 'c', 'k', '.', 's', 'h', 0}; if (nav_drive_set(LUN_ID_VIRTUAL_MEM)) { nav_drive_format(FS_FORMAT_DEFAULT); // TODO: get script into static array uint8_t _MEM_TYPE_SLOW_* script_buf; uint16_t script_size; //if (nav_file_create( (const FS_STRING) script_name ) && file_open(FOPEN_MODE_W)) { // file_write_buf(script_buf, script_size); //} file_close(); } }
Fs_file_segment ushell_cmd_perform_alloc( uint8_t lun, uint16_t size_alloc ) { const FS_STRING file_tmp_name = "tmp.bin"; Fs_file_segment g_recorder_seg; g_recorder_seg.u16_size = 0; if( !nav_drive_set(lun)) return g_recorder_seg; if( !nav_partition_mount() ) return g_recorder_seg; if( !nav_file_create((FS_STRING)file_tmp_name)) { if( FS_ERR_FILE_EXIST != fs_g_status) return g_recorder_seg; nav_file_del(false); if( !nav_file_create((FS_STRING)file_tmp_name)) return g_recorder_seg; } // Open file if( !file_open(FOPEN_MODE_W) ) { nav_file_del(false); return g_recorder_seg; } // Define the size of segment to alloc (unit 512B) // Note: you can alloc more in case of you don't know total size g_recorder_seg.u16_size = size_alloc; // Alloc in FAT a cluster list equal or inferior at segment size if( !file_write( &g_recorder_seg )) { g_recorder_seg.u16_size = 0; file_close(); nav_file_del(false); } return g_recorder_seg; //** File open and FAT allocated }
//! @brief This function initializes the hardware/software resources required for ushell task. //! void ushell_task_init(uint32_t pba_hz) { uint8_t u8_i; //** Initialize the USART used by uShell with the configured parameters static const gpio_map_t SHL_USART_GPIO_MAP = { {SHL_USART_RX_PIN, SHL_USART_RX_FUNCTION}, {SHL_USART_TX_PIN, SHL_USART_TX_FUNCTION} }; #if (defined __GNUC__) set_usart_base((void *)SHL_USART); gpio_enable_module(SHL_USART_GPIO_MAP, sizeof(SHL_USART_GPIO_MAP) / sizeof(SHL_USART_GPIO_MAP[0])); usart_init(SHL_USART_BAUDRATE); #elif (defined __ICCAVR32__) static const usart_options_t SHL_USART_OPTIONS = { .baudrate = SHL_USART_BAUDRATE, .charlength = 8, .paritytype = USART_NO_PARITY, .stopbits = USART_1_STOPBIT, .channelmode = USART_NORMAL_CHMODE }; extern volatile avr32_usart_t *volatile stdio_usart_base; stdio_usart_base = SHL_USART; gpio_enable_module(SHL_USART_GPIO_MAP, sizeof(SHL_USART_GPIO_MAP) / sizeof(SHL_USART_GPIO_MAP[0])); usart_init_rs232(SHL_USART, &SHL_USART_OPTIONS, pba_hz); #endif //** Configure standard I/O streams as unbuffered. #if (defined __GNUC__) setbuf(stdin, NULL); #endif setbuf(stdout, NULL); // Set default state of ushell g_b_ushell_task_run = false; for( u8_i=0; u8_i<USHELL_HISTORY; u8_i++ ) { g_s_cmd_his[u8_i][0] = 0; // Set end of line for all cmd line history } fputs(MSG_EXIT, stdout ); g_u32_ushell_pba_hz = pba_hz; // Save value to manage a time counter during perform command #ifdef FREERTOS_USED xTaskCreate(ushell_task, configTSK_USHELL_NAME, configTSK_USHELL_STACK_SIZE, NULL, configTSK_USHELL_PRIORITY, NULL); #endif // FREERTOS_USED } #ifdef FREERTOS_USED /*! \brief Entry point of the explorer task management. * * This function performs uShell decoding to access file-system functions. * * \param pvParameters Unused. */ void ushell_task(void *pvParameters) #else /*! \brief Entry point of the explorer task management. * * This function performs uShell decoding to access file-system functions. */ void ushell_task(void) #endif { #ifdef FREERTOS_USED //** Inifinite loop for RTOS because it is a RTOS task portTickType xLastWakeTime; xLastWakeTime = xTaskGetTickCount(); while (true) { vTaskDelayUntil(&xLastWakeTime, configTSK_USHELL_PERIOD); #else //** No loop with the basic scheduler { #endif // FREERTOS_USED //** Check the USB mode and authorize/unauthorize ushell if(!g_b_ushell_task_run) { if( Is_usb_id_device() ) #ifdef FREERTOS_USED continue; // Continue in the RTOS task #else return; // Exit of the task scheduled #endif g_b_ushell_task_run = true; // Display shell startup fputs(MSG_WELCOME, stdout); ushell_cmd_nb_drive(); fputs(MSG_PROMPT, stdout); // Reset the embedded FS on ushell navigator and on first drive nav_reset(); nav_select( FS_NAV_ID_USHELL_CMD ); nav_drive_set( 0 ); }else{ if( Is_usb_id_device() ) { g_b_ushell_task_run = false; fputs(MSG_EXIT, stdout ); nav_exit(); #ifdef FREERTOS_USED continue; // Continue in the RTOS task #else return; // Exit of the task scheduled #endif } } //** Scan shell command if( !ushell_cmd_scan() ) #ifdef FREERTOS_USED continue; // Continue in the RTOS task #else return; // Exit of the task scheduled #endif //** Command ready then decode and execute this one switch( ushell_cmd_decode() ) { // Displays number of drives case CMD_NB_DRIVE: ushell_cmd_nb_drive(); break; // Displays free space information for all connected drives case CMD_DF: ushell_cmd_free_space(); break; // Formats disk case CMD_FORMAT: ushell_cmd_format(); break; // Mounts a drive (e.g. "b:") case CMD_MOUNT: ushell_cmd_mount(); break; // Displays the space information for current drive case CMD_SPACE: ushell_cmd_space(); break; // Lists the files present in current directory (e.g. "ls") case CMD_LS: ushell_cmd_ls(false); break; case CMD_LS_MORE: ushell_cmd_ls(true); break; // Enters in a directory (e.g. "cd folder_toto") case CMD_CD: ushell_cmd_cd(); break; // Enters in parent directory ("cd..") case CMD_UP: ushell_cmd_gotoparent(); break; // Displays a text file case CMD_CAT: ushell_cmd_cat(false); break; case CMD_CAT_MORE: ushell_cmd_cat(true); break; // Displays the help case CMD_HELP: ushell_cmd_help(); break; // Creates directory case CMD_MKDIR: ushell_cmd_mkdir(); break; // Creates file case CMD_TOUCH: ushell_cmd_touch(); break; // Deletes files or directories case CMD_RM: ushell_cmd_rm(); break; // Appends char to selected file case CMD_APPEND: ushell_cmd_append_file(); break; // Index routines (= specific shortcut from ATMEL FileSystem) case CMD_SET_ID: g_mark_index = nav_getindex(); break; case CMD_GOTO_ID: nav_gotoindex( &g_mark_index ); break; // Copies file to other location case CMD_CP: ushell_cmd_copy(); break; // Renames file case CMD_MV: ushell_cmd_rename(); break; // Synchronize folders case CMD_SYNC: ushell_cmd_sync(); break; case CMD_PERFORM: ushell_cmd_perform(); break; // USB commands #if USB_HOST_FEATURE == true case CMD_LS_USB: ushell_cmdusb_ls(); break; case CMD_USB_SUSPEND: ushell_cmdusb_suspend(); break; case CMD_USB_RESUME: ushell_cmdusb_resume(); break; #endif case CMD_NONE: break; // Unknown command default: fputs(MSG_ER_CMD_NOT_FOUND, stdout); break; } fputs(MSG_PROMPT, stdout); } } //! @brief Get the full command line to be interpreted. //! //! @return true, if a command is ready //! bool ushell_cmd_scan(void) { int c_key; // Something new of the UART ? if (usart_read_char(SHL_USART, &c_key) != USART_SUCCESS) { usart_reset_status(SHL_USART); return false; } if( 0 != g_u8_escape_sequence ) { //** Decode escape sequence if( 1 == g_u8_escape_sequence ) { if( 0x5B != c_key ) { g_u8_escape_sequence=0; return false; // Escape sequence cancel } g_u8_escape_sequence=2; } else { // Decode value of the sequence switch (c_key) { /* Note: OVERRUN error on USART with an RTOS and USART without interrupt management If you want support "Escape sequence", then you have to implement USART interrupt management case 0x41: // UP command ushell_clean_cmd_line(); ushell_history_up(); ushell_history_display(); break; case 0x42: // DOWN command ushell_clean_cmd_line(); ushell_history_down(); ushell_history_display(); break; */ default: // Ignore other command break; } g_u8_escape_sequence=0; // End of Escape sequence } return false; } //** Normal sequence switch (c_key) { //** Command validation case ASCII_CR: putchar(ASCII_CR); // Echo putchar(ASCII_LF); // Add new line flag g_s_cmd_his[g_u8_history_pos][g_u8_cmd_size]=0; // Add NULL terminator at the end of command line return true; //** Enter in escape sequence case ASCII_ESCAPE: g_u8_escape_sequence=1; break; //** backspace case ASCII_BKSPACE: if(g_u8_cmd_size>0) // Beginning of line ? { // Remove the last character on terminal putchar(ASCII_BKSPACE); // Send a backspace to go in previous character putchar(' '); // Send a space to erase previous character putchar(ASCII_BKSPACE); // Send a backspace to go in new end position (=previous character position) // Remove the last character on cmd line buffer g_u8_cmd_size--; } break; // History management case '!': ushell_clean_cmd_line(); ushell_history_up(); ushell_history_display(); break; case '$': ushell_clean_cmd_line(); ushell_history_down(); ushell_history_display(); break; //** Other char default: if( (0x1F<c_key) && (c_key<0x7F) && (USHELL_SIZE_CMD_LINE!=g_u8_cmd_size) ) { // Accept char putchar(c_key); // Echo g_s_cmd_his[g_u8_history_pos][g_u8_cmd_size++] = c_key; // append to cmd line } break; } return false; }
/*! \brief Main function. Execution starts here. */ int main(void) { sysclk_init(); irq_initialize_vectors(); cpu_irq_enable(); // Initialize the sleep manager sleepmgr_init(); board_init(); ui_init(); // Reset File System nav_reset(); // Start USB host stack uhc_start(); // The USB management is entirely managed by interrupts. // As a consequence, the user application does only have : // - to play with the power modes // - to create a file on each new LUN connected while (true) { sleepmgr_enter_sleep(); if (main_usb_sof_counter > 2000) { main_usb_sof_counter = 0; uint8_t lun; for (lun = 0; (lun < uhi_msc_mem_get_lun()) && (lun < 8); lun++) { // Mount drive nav_drive_set(lun); if (!nav_partition_mount()) { if (fs_g_status == FS_ERR_HW_NO_PRESENT) { // The test can not be done, if LUN is not present lun_state &= ~(1 << lun); // LUN test reseted continue; } lun_state |= (1 << lun); // LUN test is done. ui_test_finish(false); // Test fail continue; } // Check if LUN has been already tested if (lun_state & (1 << lun)) { continue; } // Create a test file on the disk if (!nav_file_create((FS_STRING) "uhi_msc_test.txt")) { if (fs_g_status != FS_ERR_FILE_EXIST) { if (fs_g_status == FS_LUN_WP) { // Test can be done only on no write protected device continue; } lun_state |= (1 << lun); // LUN test is done. ui_test_finish(false); // Test fail continue; } } if (!file_open(FOPEN_MODE_APPEND)) { if (fs_g_status == FS_LUN_WP) { // Test can be done only on no write protected device continue; } lun_state |= (1 << lun); // LUN test is done. ui_test_finish(false); // Test fail continue; } if (!file_write_buf((uint8_t*)MSG_TEST, sizeof(MSG_TEST))) { lun_state |= (1 << lun); // LUN test is done. ui_test_finish(false); // Test fail continue; } file_close(); lun_state |= (1 << lun); // LUN test is done. ui_test_finish(true); // Test pass } if ((lun == 0) || (lun_state == 0)) { ui_test_flag_reset(); } } } }
void IBN_FileAccess (u8 nParamsGet_u8,u8 CMD_u8,u32 Param_u32) { s32 FileID_s32; s32 Ret_s32; // testtt[1000] = 4; if (0 == nParamsGet_u8) { CI_LocalPrintf ("File access\r\n"); CI_LocalPrintf (" 0 = Set lun 0\r\n"); CI_LocalPrintf (" 1 = Mount\r\n"); CI_LocalPrintf (" 2 = Show free space\r\n"); CI_LocalPrintf ("11 = Set BUSY Lun 0\r\n"); CI_LocalPrintf ("12 = Update contend lun X\r\n"); CI_LocalPrintf ("16 = Copy test.txt to test1.txt\n\r"); CI_LocalPrintf ("17 = Format LUN X\n\r"); return; } switch (CMD_u8) { case 0 : fs_g_nav.u8_lun = 0; // On chip RAM break; #if LUN_2 == ENABLE case 1 : if (2 != nParamsGet_u8) { CI_LocalPrintf ("USAGE: fa 1 [lun]\r\n"); break; } b_fsaccess_init (); fs_g_nav.u8_lun = Param_u32; // On chip RAM virtual_test_unit_ready() ; if (TRUE == fat_mount ()) { CI_LocalPrintf ("Mount LUN %d OK\r\n",Param_u32); } else { CI_LocalPrintf ("Mount LUN %d FAIL - %d - %s\r\n",Param_u32,fs_g_status, IBN_FileSystemErrorText(fs_g_status)); } // nav_partition_mount (); break; #endif case 2 : CI_LocalPrintf ("Free mem = %d sectors\r\n",fat_getfreespace()); break; case 3 : FileID_s32 = open ("test.txt",O_CREAT|O_RDWR); CI_LocalPrintf ("Open = %d - %d - %s\r\n",FileID_s32,fs_g_status, IBN_FileSystemErrorText(fs_g_status)); Ret_s32 = write (FileID_s32,"Test\n",6); CI_LocalPrintf ("Write = %d \r\n",Ret_s32); /* if (TRUE == fat_cache_flush ()) { CI_LocalPrintf ("fat_cache_flush OK\r\n"); } else { CI_LocalPrintf ("fat_cache_flush FAIL - %d - %s\r\n",fs_g_status, IBN_FileSystemErrorText(fs_g_status)); } */ Ret_s32 = close (FileID_s32); CI_LocalPrintf ("Close = %d \r\n",Ret_s32); #if LUN_2 == ENABLE virtual_unit_state_e = CTRL_BUSY; // only for ram disk #endif sd_mmc_mci_unit_state_e = CTRL_BUSY; vTaskDelay (500); #if LUN_2 == ENABLE virtual_unit_state_e = CTRL_GOOD; #endif sd_mmc_mci_unit_state_e = CTRL_GOOD; break; case 4 : if (2 != nParamsGet_u8) { CI_LocalPrintf ("USAGE: fa 6 [lun]\r\n"); break; } FAI_Write (Param_u32); break; case 5 : FAI_ShowDirContent (); break; case 6: if (2 != nParamsGet_u8) { CI_LocalPrintf ("USAGE: fa 6 [lun]\r\n"); break; } FAI_mount(Param_u32); break; case 7 : FAI_free_space(Param_u32); break; case 8 : FAI_nb_drive(); break; case 9 : FAI_Dir (0); break; case 10 : if (TRUE == nav_drive_set (Param_u32)) { CI_LocalPrintf ("nav_drive_set OK\r\n"); } else { CI_LocalPrintf ("nav_drive_set FAIL - %d - %s\r\n",fs_g_status, IBN_FileSystemErrorText(fs_g_status)); } break; case 11 : #if LUN_2 == ENABLE CI_LocalPrintf ("Set LUN %d CTRL_BUSY\n\r",Param_u32); //virtual_unit_state_e = CTRL_BUSY; set_virtual_unit_busy (); #endif break; case 12 : CI_LocalPrintf ("Update LUN %d\n\r",Param_u32); FAI_UpdateContend (Param_u32);; break; case 13 : CI_LocalPrintf ("fat_cache_flush\n\r"); fat_cache_flush (); break; case 14 : CI_LocalPrintf ("fat_check_device\n\r"); fat_check_device (); break; case 15 : CI_LocalPrintf ("fat_check_device\n\r"); fat_read_dir (); break; case 16 : CI_LocalPrintf ("Copy test.txt to test1.txt\n\r"); { u8 F1[10]; u8 F2[10]; strcpy ((char*)F1,"test.txt"); strcpy ((char*)F2,"test1.txt"); FAI_CopyFile (F1,F2); } break; case 17 : CI_LocalPrintf ("Format LUN %d\n\r",Param_u32); nav_drive_set(Param_u32); if( !nav_drive_format(FS_FORMAT_FAT) ) { CI_LocalPrintf ("Format LUN %d - ERROR\n\r",Param_u32); } break; } }