/** * \brief Miscellaneous functions, which support the following commands: * * CTRL_SYNC Make sure that the disk drive has finished pending write * process. When the disk I/O module has a write back cache, flush the * dirty sector immediately. * In read-only configuration, this command is not needed. * * GET_SECTOR_COUNT Return total sectors on the drive into the DWORD variable * pointed by buffer. * This command is used only in f_mkfs function. * * GET_BLOCK_SIZE Return erase block size of the memory array in unit * of sector into the DWORD variable pointed by Buffer. * When the erase block size is unknown or magnetic disk device, return 1. * This command is used only in f_mkfs function. * * GET_SECTOR_SIZE Return sector size of the memory array. * * \param drv Physical drive number (0..). * \param ctrl Control code. * \param buff Buffer to send/receive control data. * * \return RES_OK for success, otherwise DRESULT error code. */ DRESULT disk_ioctl(BYTE drv, BYTE ctrl, void *buff) { DRESULT res = RES_PARERR; switch (ctrl) { case GET_BLOCK_SIZE: *(DWORD *)buff = 1; res = RES_OK; break; /* Get the number of sectors on the disk (DWORD) */ case GET_SECTOR_COUNT: { uint32_t ul_last_sector_num; /* Check valid address */ mem_read_capacity(drv, &ul_last_sector_num); *(DWORD *)buff = ul_last_sector_num + 1; res = RES_OK; } break; /* Get sectors on the disk (WORD) */ case GET_SECTOR_SIZE: { uint8_t uc_sector_size = mem_sector_size(drv); if ((uc_sector_size != SECTOR_SIZE_512) && (uc_sector_size != SECTOR_SIZE_1024) && (uc_sector_size != SECTOR_SIZE_2048) && (uc_sector_size != SECTOR_SIZE_4096)) { /* The sector size is not supported by the FatFS */ return RES_ERROR; } *(uint8_t *)buff = uc_sector_size * SECTOR_SIZE_DEFAULT; res = RES_OK; } break; /* Make sure that data has been written */ case CTRL_SYNC: if (mem_test_unit_ready(drv) == CTRL_GOOD) { res = RES_OK; } else { res = RES_NOTRDY; } break; default: res = RES_PARERR; } return res; }
/** * \brief Return disk status. * * \param drv Physical drive number (0..). * * \return 0 or disk status in combination of DSTATUS bits * (STA_NOINIT, STA_NODISK, STA_PROTECT). */ DSTATUS disk_status(BYTE drv) { switch (mem_test_unit_ready(drv)) { case CTRL_GOOD: return 0; case CTRL_NO_PRESENT: return STA_NOINIT | STA_NODISK; default: return STA_NOINIT; } }
/** * \brief Return disk status. * * \param drv Physical drive number (0..). * * \return 0 or disk status in combination of DSTATUS bits * (STA_NOINIT, STA_NODISK, STA_PROTECT). */ DSTATUS disk_status(BYTE drv) { MutexLocker lock((drv >= SD_MMC_HSMCI_MEM_CNT) ? Tasks::GetSpiMutex() : nullptr); switch (mem_test_unit_ready(drv)) { case CTRL_GOOD: return 0; case CTRL_NO_PRESENT: return STA_NOINIT | STA_NODISK; default: return STA_NOINIT; } }
/** * \brief Initialize a disk. * * \param drv Physical drive number (0..). * * \return 0 or disk status in combination of DSTATUS bits * (STA_NOINIT, STA_PROTECT). */ DSTATUS disk_initialize(BYTE drv) { int i; Ctrl_status mem_status; #if 0 /* Default RTC configuration, 24-hour mode */ rtc_set_hour_mode(RTC, 0); #endif #if 0 configure_rtc_calendar(); #endif #if LUN_USB /* USB disk with multiple LUNs */ if (drv > LUN_ID_USB + Lun_usb_get_lun()) { return STA_NOINIT; } #else if (drv > MAX_LUN) { /* At least one of the LUN should be defined */ return STA_NOINIT; } #endif /* Check LUN ready (USB disk report CTRL_BUSY then CTRL_GOOD) */ for (i = 0; i < 2; i ++) { mem_status = mem_test_unit_ready(drv); if (CTRL_BUSY != mem_status) { break; } } if (mem_status != CTRL_GOOD) { return STA_NOINIT; } /* Check Write Protection Status */ if (mem_wr_protect(drv)) { return STA_PROTECT; } /* The memory should already be initialized */ return 0; }
/** * \brief Initialize a disk. * * \param drv Physical drive number (0..). * * \return 0 or disk status in combination of DSTATUS bits * (STA_NOINIT, STA_PROTECT). */ DSTATUS disk_initialize(BYTE drv) { #if LUN_USB /* USB disk with multiple LUNs */ if (drv > LUN_ID_USB + Lun_usb_get_lun()) { return STA_NOINIT; } #else if (drv > MAX_LUN) { /* At least one of the LUN should be defined */ return STA_NOINIT; } #endif MutexLocker lock((drv >= SD_MMC_HSMCI_MEM_CNT) ? Tasks::GetSpiMutex() : nullptr); Ctrl_status mem_status; /* Check LUN ready (USB disk report CTRL_BUSY then CTRL_GOOD) */ for (int i = 0; i < 2; i ++) { mem_status = mem_test_unit_ready(drv); if (CTRL_BUSY != mem_status) { break; } } if (mem_status != CTRL_GOOD) { return STA_NOINIT; } /* Check Write Protection Status */ if (mem_wr_protect(drv)) { return STA_PROTECT; } /* The memory should already be initialized */ return 0; }
Bool sbc_test_unit_ready (void) { switch (mem_test_unit_ready (usb_LUN)) { case CTRL_GOOD: sbc_lun_status_is_good (); break; case CTRL_NO_PRESENT: sbc_lun_status_is_not_present (); break; case CTRL_BUSY: sbc_lun_status_is_busy_or_change (); break; case CTRL_FAIL: default: sbc_lun_status_is_fail (); break; } return TRUE; }
/*! \brief Sets up USART for shell. * * \param pba_hz The current module frequency. */ static void init_shl_rs232(long pba_hz) { // GPIO map for USART. 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} }; // Options for USART. 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 }; // Set up GPIO for SHL_USART, size of the GPIO map is 2 here. gpio_enable_module(SHL_USART_GPIO_MAP, sizeof(SHL_USART_GPIO_MAP) / sizeof(SHL_USART_GPIO_MAP[0])); // Initialize it in RS232 mode. usart_init_rs232(SHL_USART, &SHL_USART_OPTIONS, pba_hz); } /*! \brief Initializes the dataflash memory AT45DBX resources: GPIO, SPI and AT45DBX. */ static void at45dbx_resources_init(void) { // GPIO map for SPI. static const gpio_map_t AT45DBX_SPI_GPIO_MAP = { {AT45DBX_SPI_SCK_PIN, AT45DBX_SPI_SCK_FUNCTION }, // SPI Clock. {AT45DBX_SPI_MISO_PIN, AT45DBX_SPI_MISO_FUNCTION }, // MISO. {AT45DBX_SPI_MOSI_PIN, AT45DBX_SPI_MOSI_FUNCTION }, // MOSI. #define AT45DBX_ENABLE_NPCS_PIN(NPCS, unused) \ {AT45DBX_SPI_NPCS##NPCS##_PIN, AT45DBX_SPI_NPCS##NPCS##_FUNCTION}, // Chip Select NPCS. MREPEAT(AT45DBX_MEM_CNT, AT45DBX_ENABLE_NPCS_PIN, ~) #undef AT45DBX_ENABLE_NPCS_PIN }; // Options for SPI. spi_options_t spiOptions = { .reg = AT45DBX_SPI_FIRST_NPCS, // Defined in conf_at45dbx.h. .baudrate = AT45DBX_SPI_MASTER_SPEED, // Defined in conf_at45dbx.h. .bits = AT45DBX_SPI_BITS, // Defined in conf_at45dbx.h. .spck_delay = 0, .trans_delay = 0, .stay_act = 1, .spi_mode = 0, .modfdis = 1 }; // Assign I/Os to SPI. gpio_enable_module(AT45DBX_SPI_GPIO_MAP, sizeof(AT45DBX_SPI_GPIO_MAP) / sizeof(AT45DBX_SPI_GPIO_MAP[0])); // Initialize as master. spi_initMaster(AT45DBX_SPI, &spiOptions); // Set selection mode: variable_ps, pcs_decode, delay. spi_selectionMode(AT45DBX_SPI, 0, 0, 0); // Enable SPI. spi_enable(AT45DBX_SPI); // Initialize data flash with SPI clock Osc0. at45dbx_init(spiOptions, FOSC0); } /*! \brief Main function. Execution starts here. */ int main(void) { U8 i, j; U16 file_size; Fs_index sav_index; static Fs_index mark_index; const char *part_type; U32 VarTemp; // Switch to external oscillator 0. pcl_switch_to_osc(PCL_OSC0, FOSC0, OSC0_STARTUP); // Initialize RS232 shell text output. init_shl_rs232(FOSC0); // Initialize AT45DBX resources: GPIO, SPI and AT45DBX. at45dbx_resources_init(); // Display memory status print(SHL_USART, MSG_WELCOME "\nMemory "); // Test if the memory is ready - using the control access memory abstraction layer (/SERVICES/MEMORY/CTRL_ACCESS/) if (mem_test_unit_ready(LUN_ID_AT45DBX_MEM) == CTRL_GOOD) { // Get and display the capacity mem_read_capacity(LUN_ID_AT45DBX_MEM, &VarTemp); print(SHL_USART, "OK:\t"); print_ulong(SHL_USART, (VarTemp + 1) >> (20 - FS_SHIFT_B_TO_SECTOR)); print(SHL_USART, " MB\n"); }
//! //! \fn main //! \brief 1) Initialize the microcontroller and the shared hardware resources //! of the board. //! 2) Launch the Ctrl Panel modules. //! 3) Start FreeRTOS. //! \return Should never occur. //! \note //! int main(void) { // Disable the WDT. // wdt_disable(); //** //** 1) Initialize the microcontroller and the shared hardware resources of the board. //** // switch to external oscillator 0 pm_switch_to_osc0(&AVR32_PM, FOSC0, OSC0_STARTUP); // Init USB & MACB clock. prv_clk_gen_start(); // initialize AT45DBX resources: GPIO, SPI and AT45DBX prv_at45dbx_resources_init(); #if SD_MMC_SPI_MEM == ENABLE prv_sd_mmc_resources_init(); #endif // Setup the LED's for output. LED_Off( LED0 ); LED_Off( LED1 ); LED_Off( LED2 ); LED_Off( LED3 ); LED_Off( LED4 ); LED_Off( LED5 ); LED_Off( LED6 ); LED_Off( LED7 ); // vParTestInitialise(); // Init the memory module. if (false == ctrl_access_init()) { // TODO: Add msg on LCD. // gpio_clr_gpio_pin( 60 ); while (1); } /* check if the AT45DBX mem is OK */ while (CTRL_GOOD != mem_test_unit_ready( LUN_ID_AT45DBX_MEM )) { // TODO: Add msg on LCD. // gpio_clr_gpio_pin( 61 ); } // Init the FAT navigation module. if (false == b_fsaccess_init()) { // TODO: Add msg on LCD. // gpio_clr_gpio_pin( 62 ); while (true); } // Init the time module. v_cptime_Init(); //** //** 2) Launch the Control Panel supervisor task that will in turn create all //** the necessary tasks. //** vSupervisor_Start( mainSUPERVISOR_TASK_PRIORITY ); //** //** 3) Start FreeRTOS. //** // Use preemptive scheduler define configUSE_PREEMPTION as 1 in portmacro.h vTaskStartScheduler(); /* Should never reach this point. */ while (true); }