Bool sbc_read_capacity (void) { U32 mem_size_nb_sector; switch (mem_read_capacity (usb_LUN, &mem_size_nb_sector)) { case CTRL_GOOD: Usb_reset_endpoint_fifo_access (g_scsi_ep_ms_in); // Return nb block. Usb_write_endpoint_data (g_scsi_ep_ms_in, 32, sbc_format_mcu_to_scsi_data (32, mem_size_nb_sector)); // Return block size (= 512 bytes). Usb_write_endpoint_data (g_scsi_ep_ms_in, 32, Sbc_format_mcu_to_scsi_data (32, 512)); Sbc_valid_write_usb (SBC_READ_CAPACITY_LENGTH); sbc_lun_status_is_good (); return TRUE; 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 FALSE; }
DRESULT disk_write(BYTE drv, BYTE const *buff, DWORD sector, UINT count) { #if ACCESS_MEM_TO_RAM uint8_t uc_sector_size = mem_sector_size(drv); uint32_t i; uint32_t ul_last_sector_num; if (uc_sector_size == 0) { return RES_ERROR; } /* Check valid address */ mem_read_capacity(drv, &ul_last_sector_num); if ((sector + count * uc_sector_size) > (ul_last_sector_num + 1) * uc_sector_size) { return RES_PARERR; } /* Write the data */ for (i = 0; i < count; i++) { if (ram_2_memory(drv, sector + uc_sector_size * i, buff + uc_sector_size * SECTOR_SIZE_DEFAULT * i) != CTRL_GOOD) { return RES_ERROR; } } return RES_OK; #else return RES_ERROR; #endif }
/** * \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; }
DRESULT disk_write(BYTE drv, BYTE const *buff, DWORD sector, BYTE count) { if (reprap.Debug(moduleStorage)) { debugPrintf("Write %u %u %lu\n", drv, count, sector); } #if ACCESS_MEM_TO_RAM MutexLocker lock((drv >= SD_MMC_HSMCI_MEM_CNT) ? Tasks::GetSpiMutex() : nullptr); const uint8_t uc_sector_size = mem_sector_size(drv); if (uc_sector_size == 0) { return RES_ERROR; } /* Check valid address */ uint32_t ul_last_sector_num; mem_read_capacity(drv, &ul_last_sector_num); if ((sector + count * uc_sector_size) > (ul_last_sector_num + 1) * uc_sector_size) { return RES_PARERR; } /* Write the data */ unsigned int retryNumber = 0; while (ram_2_memory(drv, sector, buff, count) != CTRL_GOOD) { ++retryNumber; if (retryNumber == MaxSdCardTries) { return RES_ERROR; } delay(SdCardRetryDelay); } if (retryNumber > highestSdRetriesDone) { highestSdRetriesDone = retryNumber; } return RES_OK; #else return RES_ERROR; #endif }
/*! \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"); }