示例#1
0
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;
}
示例#2
0
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;
}
示例#3
0
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;
}
示例#4
0
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
    }
}
示例#5
0
// 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);
}
示例#6
0
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;
}
示例#7
0
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;
}
示例#8
0
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
    }
}
示例#9
0
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;
}