int32_t flash_bdev_ioctl(uint32_t op, uint32_t arg) { (void)arg; switch (op) { case BDEV_IOCTL_INIT: flash_flags = 0; flash_cache_sector_id = 0; flash_tick_counter_last_write = 0; return 0; case BDEV_IOCTL_NUM_BLOCKS: return FLASH_MEM_SEG1_NUM_BLOCKS + FLASH_MEM_SEG2_NUM_BLOCKS; case BDEV_IOCTL_IRQ_HANDLER: flash_bdev_irq_handler(); return 0; case BDEV_IOCTL_SYNC: { uint32_t basepri = raise_irq_pri(IRQ_PRI_FLASH); // prevent cache flushing and USB access if (flash_flags & FLASH_FLAG_DIRTY) { flash_flags |= FLASH_FLAG_FORCE_WRITE; while (flash_flags & FLASH_FLAG_DIRTY) { flash_bdev_irq_handler(); } } restore_irq_pri(basepri); return 0; } } return -MP_EINVAL; }
mp_uint_t sdcard_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks) { // check that SD card is initialised if (sd_handle.Instance == NULL) { return SD_ERROR; } HAL_SD_ErrorTypedef err = SD_OK; // check that dest pointer is aligned on a 4-byte boundary uint8_t *orig_dest = NULL; uint32_t saved_word; if (((uint32_t)dest & 3) != 0) { // Pointer is not aligned so it needs fixing. // We could allocate a temporary block of RAM (as sdcard_write_blocks // does) but instead we are going to use the dest buffer inplace. We // are going to align the pointer, save the initial word at the aligned // location, read into the aligned memory, move the memory back to the // unaligned location, then restore the initial bytes at the aligned // location. We should have no trouble doing this as those initial // bytes at the aligned location should be able to be changed for the // duration of this function call. orig_dest = dest; dest = (uint8_t*)((uint32_t)dest & ~3); saved_word = *(uint32_t*)dest; } if (query_irq() == IRQ_STATE_ENABLED) { // we must disable USB irqs to prevent MSC contention with SD card uint32_t basepri = raise_irq_pri(IRQ_PRI_OTG_FS); dma_init(&sd_rx_dma, &SDMMC_RX_DMA, &sd_handle); sd_handle.hdmarx = &sd_rx_dma; // make sure cache is flushed and invalidated so when DMA updates the RAM // from reading the peripheral the CPU then reads the new data MP_HAL_CLEANINVALIDATE_DCACHE(dest, num_blocks * SDCARD_BLOCK_SIZE); err = HAL_SD_ReadBlocks_BlockNumber_DMA(&sd_handle, (uint32_t*)dest, block_num, SDCARD_BLOCK_SIZE, num_blocks); if (err == SD_OK) { // wait for DMA transfer to finish, with a large timeout err = HAL_SD_CheckReadOperation(&sd_handle, 100000000); } dma_deinit(&SDMMC_RX_DMA); sd_handle.hdmarx = NULL; restore_irq_pri(basepri); } else { err = HAL_SD_ReadBlocks_BlockNumber(&sd_handle, (uint32_t*)dest, block_num, SDCARD_BLOCK_SIZE, num_blocks); } if (orig_dest != NULL) { // move the read data to the non-aligned position, and restore the initial bytes memmove(orig_dest, dest, num_blocks * SDCARD_BLOCK_SIZE); memcpy(dest, &saved_word, orig_dest - dest); } return err; }
mp_uint_t sdcard_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks) { // check that SD card is initialised if (sd_handle.Instance == NULL) { return HAL_ERROR; } HAL_StatusTypeDef err = HAL_OK; // check that src pointer is aligned on a 4-byte boundary if (((uint32_t)src & 3) != 0) { // pointer is not aligned, so allocate a temporary block to do the write uint8_t *src_aligned = m_new_maybe(uint8_t, SDCARD_BLOCK_SIZE); if (src_aligned == NULL) { return HAL_ERROR; } for (size_t i = 0; i < num_blocks; ++i) { memcpy(src_aligned, src + i * SDCARD_BLOCK_SIZE, SDCARD_BLOCK_SIZE); err = sdcard_write_blocks(src_aligned, block_num + i, 1); if (err != HAL_OK) { break; } } m_del(uint8_t, src_aligned, SDCARD_BLOCK_SIZE); return err; } if (query_irq() == IRQ_STATE_ENABLED) { // we must disable USB irqs to prevent MSC contention with SD card uint32_t basepri = raise_irq_pri(IRQ_PRI_OTG_FS); #if SDIO_USE_GPDMA dma_init(&sd_tx_dma, &SDMMC_TX_DMA, &sd_handle); sd_handle.hdmatx = &sd_tx_dma; #endif // make sure cache is flushed to RAM so the DMA can read the correct data MP_HAL_CLEAN_DCACHE(src, num_blocks * SDCARD_BLOCK_SIZE); err = HAL_SD_WriteBlocks_DMA(&sd_handle, (uint8_t*)src, block_num, num_blocks); if (err == HAL_OK) { err = sdcard_wait_finished(&sd_handle, 60000); } #if SDIO_USE_GPDMA dma_deinit(&SDMMC_TX_DMA); sd_handle.hdmatx = NULL; #endif restore_irq_pri(basepri); } else { err = HAL_SD_WriteBlocks(&sd_handle, (uint8_t*)src, block_num, num_blocks, 60000); if (err == HAL_OK) { err = sdcard_wait_finished(&sd_handle, 60000); } } return err; }
bool storage_read_block(uint8_t *dest, uint32_t block) { //printf("RD %u\n", block); if (block == 0) { // fake the MBR so we can decide on our own partition table for (int i = 0; i < 446; i++) { dest[i] = 0; } build_partition(dest + 446, 0, 0x01 /* FAT12 */, FLASH_PART1_START_BLOCK, FLASH_PART1_NUM_BLOCKS); build_partition(dest + 462, 0, 0, 0, 0); build_partition(dest + 478, 0, 0, 0, 0); build_partition(dest + 494, 0, 0, 0, 0); dest[510] = 0x55; dest[511] = 0xaa; return true; } else { #if USE_INTERNAL // non-MBR block, get data from flash memory, possibly via cache uint32_t flash_addr = convert_block_to_flash_addr(block); if (flash_addr == -1) { // bad block number return false; } uint8_t *src = flash_cache_get_addr_for_read(flash_addr); memcpy(dest, src, FLASH_BLOCK_SIZE); return true; #else // non-MBR block, get data from SPI flash if (block < FLASH_PART1_START_BLOCK || block >= FLASH_PART1_START_BLOCK + FLASH_PART1_NUM_BLOCKS) { // bad block number return false; } // we must disable USB irqs to prevent MSC contention with SPI flash uint32_t basepri = raise_irq_pri(IRQ_PRI_OTG_FS); mp_spiflash_read((mp_spiflash_t*)&spiflash, (block - FLASH_PART1_START_BLOCK) * FLASH_BLOCK_SIZE, FLASH_BLOCK_SIZE, dest); restore_irq_pri(basepri); return true; #endif } }
// Attempt to queue data on the USB IN endpoint static void usbd_cdc_try_tx(usbd_cdc_itf_t *cdc) { uint32_t basepri = raise_irq_pri(IRQ_PRI_OTG_FS); if (cdc == NULL || cdc->connect_state == USBD_CDC_CONNECT_STATE_DISCONNECTED) { // CDC device is not connected to a host, so we are unable to send any data } else if (cdc->base.tx_in_progress) { // USB driver will call callback when ready } else { usbd_cdc_tx_ready(&cdc->base); } restore_irq_pri(basepri); }
bool flash_bdev_writeblock(const uint8_t *src, uint32_t block) { // non-MBR block, copy to cache uint32_t flash_addr = convert_block_to_flash_addr(block); if (flash_addr == -1) { // bad block number return false; } uint32_t basepri = raise_irq_pri(IRQ_PRI_FLASH); // prevent cache flushing and USB access uint8_t *dest = flash_cache_get_addr_for_write(flash_addr); memcpy(dest, src, FLASH_BLOCK_SIZE); restore_irq_pri(basepri); return true; }
mp_uint_t sdcard_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks) { // check that SD card is initialised if (sd_handle.Instance == NULL) { return SD_ERROR; } HAL_SD_ErrorTypedef err = SD_OK; // check that src pointer is aligned on a 4-byte boundary if (((uint32_t)src & 3) != 0) { // pointer is not aligned, so allocate a temporary block to do the write uint8_t *src_aligned = m_new_maybe(uint8_t, SDCARD_BLOCK_SIZE); if (src_aligned == NULL) { return SD_ERROR; } for (size_t i = 0; i < num_blocks; ++i) { memcpy(src_aligned, src + i * SDCARD_BLOCK_SIZE, SDCARD_BLOCK_SIZE); err = sdcard_write_blocks(src_aligned, block_num + i, 1); if (err != SD_OK) { break; } } m_del(uint8_t, src_aligned, SDCARD_BLOCK_SIZE); return err; } if (query_irq() == IRQ_STATE_ENABLED) { // we must disable USB irqs to prevent MSC contention with SD card uint32_t basepri = raise_irq_pri(IRQ_PRI_OTG_FS); dma_init(&sd_tx_dma, &dma_SDIO_0_TX, &sd_handle); sd_handle.hdmatx = &sd_tx_dma; err = HAL_SD_WriteBlocks_BlockNumber_DMA(&sd_handle, (uint32_t*)src, block_num, SDCARD_BLOCK_SIZE, num_blocks); if (err == SD_OK) { // wait for DMA transfer to finish, with a large timeout err = HAL_SD_CheckWriteOperation(&sd_handle, 100000000); } dma_deinit(&dma_SDIO_0_TX); sd_handle.hdmatx = NULL; restore_irq_pri(basepri); } else { err = HAL_SD_WriteBlocks_BlockNumber(&sd_handle, (uint32_t*)src, block_num, SDCARD_BLOCK_SIZE, num_blocks); } return err; }
bool storage_write_block(const uint8_t *src, uint32_t block) { //printf("WR %u\n", block); if (block == 0) { // can't write MBR, but pretend we did return true; } else { #if USE_INTERNAL // non-MBR block, copy to cache uint32_t flash_addr = convert_block_to_flash_addr(block); if (flash_addr == -1) { // bad block number return false; } uint8_t *dest = flash_cache_get_addr_for_write(flash_addr); memcpy(dest, src, FLASH_BLOCK_SIZE); return true; #else // non-MBR block, write to SPI flash if (block < FLASH_PART1_START_BLOCK || block >= FLASH_PART1_START_BLOCK + FLASH_PART1_NUM_BLOCKS) { // bad block number return false; } // we must disable USB irqs to prevent MSC contention with SPI flash uint32_t basepri = raise_irq_pri(IRQ_PRI_OTG_FS); int ret = mp_spiflash_write((mp_spiflash_t*)&spiflash, (block - FLASH_PART1_START_BLOCK) * FLASH_BLOCK_SIZE, FLASH_BLOCK_SIZE, src); restore_irq_pri(basepri); return ret == 0; #endif } }
mp_uint_t sdcard_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks) { // check that dest pointer is aligned on a 4-byte boundary if (((uint32_t)dest & 3) != 0) { return SD_ERROR; } // check that SD card is initialised if (sd_handle.Instance == NULL) { return SD_ERROR; } HAL_SD_ErrorTypedef err = SD_OK; if (query_irq() == IRQ_STATE_ENABLED) { // we must disable USB irqs to prevent MSC contention with SD card uint32_t basepri = raise_irq_pri(IRQ_PRI_OTG_FS); dma_init(&sd_rx_dma, DMA_STREAM_SDIO_RX, &dma_init_struct_sdio, DMA_CHANNEL_SDIO_RX, DMA_PERIPH_TO_MEMORY, &sd_handle); sd_handle.hdmarx = &sd_rx_dma; err = HAL_SD_ReadBlocks_BlockNumber_DMA(&sd_handle, (uint32_t*)dest, block_num, SDCARD_BLOCK_SIZE, num_blocks); if (err == SD_OK) { // wait for DMA transfer to finish, with a large timeout err = HAL_SD_CheckReadOperation(&sd_handle, 100000000); } dma_deinit(sd_handle.hdmarx); sd_handle.hdmarx = NULL; restore_irq_pri(basepri); } else { err = HAL_SD_ReadBlocks_BlockNumber(&sd_handle, (uint32_t*)dest, block_num, SDCARD_BLOCK_SIZE, num_blocks); } return err; }