/*! \brief Release a system mutex. * * \param xSemaphore A handle to the semaphore being released. * * \return pdTRUE if the semaphore was released. pdFALSE if an error occurred. */ portBASE_TYPE x_supervisor_SemaphoreGive( xSemaphoreHandle xSemaphore ) { #ifdef USB_ENABLE #if USB_DEVICE_FEATURE == true if( ( 0 != u8IsMaintenanceRequired ) && ( false == bOutOfMaintenance ) ) { // If we have to enter in the maintenance mode, do not release the mutex. // => this mutex is now the property of the supervisor. u8IsMaintenanceRequired++; // If all mutexes have been acquired, switch to maintenance mode. if( ( SUPERVISOR_MAINTENANCE_NBMUTEX_TOTAKE +1 ) == u8IsMaintenanceRequired ) { fat_cache_flush(); // Flush the FAT cache. nav_reset(); // Reset all file system navigators. We will mount // the com1shell default drive when we'll leave the // maintenance mode. // Switch to maintenance mode. xSemaphoreGive( xUSBMutex ); // If the USB clock is frozen, unfreeze it so that we can write in the // USB registers. The USB clock is frozen if a "Device Suspend" event // occurred (no more USB activity detected) (cf. usb_general_interrupt()). if(true == Is_usb_clock_frozen()) { Usb_unfreeze_clock(); } // If it is not already detached, physically detach the USB device. if(false == Is_usb_detached()) { Usb_detach(); } vTaskDelay(500); // Wait 500ms Usb_attach(); // Reconnect the device. bIsInMaintenance = true; u8IsMaintenanceRequired = 0; TRACE_COM2( "Entering maintenance mode"); #ifdef MMILCD_ENABLE vMMI_SetUserMenuMode( eUserMenuWaitHost, pdTRUE ); #endif } return( pdTRUE ); } else #endif #endif return( xSemaphoreGive( xSemaphore ) ); }
//! //! This function initializes mutex and navigators. //! bool b_fsaccess_init(void) { nav_reset(); #ifdef FREERTOS_USED if (xFs_Access == NULL) { vSemaphoreCreateBinary( xFs_Access ); if( xFs_Access == NULL ) return( false ); else return( true ); } #endif return( true ); }
//! //! @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 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 The switch-to-maintenance-mode command: initiate the process to \n * switch to maintenance mode. * Format: maintain * * \note This function must be of the type pfShellCmd defined by the shell module. * * \param xModId Input. The module that is calling this function. * \param FsNavId Ignored. * \param ac Ignored. * \param av Ignored. * \param ppcStringReply Input/Output. The response string. * If Input is NULL, no response string will be output. * Else a malloc for the response string is performed here; * the caller must free this string. * * \return the status of the command execution. */ eExecStatus e_supervisor_switch_to_maintenance_mode( eModId xModId, signed short FsNavId, int ac, signed portCHAR *av[], signed portCHAR **ppcStringReply ) { if( NULL != ppcStringReply ) *ppcStringReply = NULL; #ifdef USB_ENABLE #if USB_DEVICE_FEATURE == true if( ( false == bIsInMaintenance ) && ( 0 == u8IsMaintenanceRequired ) ) { // We're not in maintenance mode. // Initiate the process of switching to maintenance mode. if( 0 == u8IsMaintenanceRequired ) u8IsMaintenanceRequired++; // Take all maintenance mutex except the USB mutex. if( true == x_supervisor_SemaphoreTake( xLOGMutex, 0 ) ) u8IsMaintenanceRequired++; #if NW_INTEGRATED_IN_CONTROL_PANEL if( true == x_supervisor_SemaphoreTake( xWEBMutex, 0 ) ) u8IsMaintenanceRequired++; #endif if( true == x_supervisor_SemaphoreTake( xSHELLFSMutex, 0 ) ) u8IsMaintenanceRequired++; if( true == x_supervisor_SemaphoreTake( xCFGMutex, 0 ) ) u8IsMaintenanceRequired++; // If all mutexes have been acquired, switch to maintenance mode. if( ( SUPERVISOR_MAINTENANCE_NBMUTEX_TOTAKE +1 ) == u8IsMaintenanceRequired ) { fat_cache_flush(); // flush the FAT cache. nav_reset(); // Reset all file system navigators. We will mount // the com1shell default drive when we'll leave the // maintenance mode. // Switch to maintenance mode. xSemaphoreGive( xUSBMutex ); // If the USB clock is frozen, unfreeze it so that we can write in the // USB registers. if(true == Is_usb_clock_frozen()) { Usb_unfreeze_clock(); } // If it is not akready detached, physically detach the USB device. if(false == Is_usb_detached()) { Usb_detach(); } vTaskDelay(500); // Wait 500ms Usb_attach(); // Reconnect the device. bIsInMaintenance = true; u8IsMaintenanceRequired = 0; TRACE_COM2( "Entering maintenance mode"); #ifdef MMILCD_ENABLE vMMI_SetUserMenuMode( eUserMenuWaitHost, pdTRUE ); #endif } // ELSE: we'll switch to maintenance mode in x_supervisor_SemaphoreGive() // (when the mutex(es) that we couldn't get will be released). } else { NAKED_TRACE_COM2( "Won't go to maintenance mode:"CRLF"bIsInMaintenance=%d u8CurrentUsbRole=%d u8IsMaintenanceRequired=%d", bIsInMaintenance, u8CurrentUsbRole, u8IsMaintenanceRequired ); } #endif #endif return( SHELL_EXECSTATUS_OK ); }
/*! \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(); } } } }