Electrical – STM32F103C8 + W25Q64 USB Mass Storage Device

fatflashspistm32usb

I have problems creating an MSC device.
I made the following functions:

#define STORAGE_BLK_NBR      0x4000
#define STORAGE_BLK_SIZ        0x200

    int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr,
        uint16_t blk_len) {
    w25qReadPage(buf, blk_addr*2);
    w25qReadPage(buf+256, blk_addr*2 + 1);
    return (USBD_OK);
}

int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr,
        uint16_t blk_len) {
    w25qWritingByUSB(blk_addr, buf);
    return (USBD_OK);
}

Read, Erase and Write:

void w25qReadPage(uint8_t *page, uint16_t pagenum) {

    uint8_t com[5] = { W25Q_READ_PAGE, (uint8_t) (pagenum >> 8),
            (uint8_t) (pagenum & 0x00FF), 0x00, 0x00 };

    W25Q_CS_LO();

    HAL_SPI_Transmit(W25Q_SPI, com, 5, 100);

    HAL_SPI_Receive(W25Q_SPI, page, W25Q_PAGE_LEN, 100);
    W25Q_CS_HI();
}

void w25qWritePage(uint8_t *page, uint16_t pagenum) {

    uint8_t temp[4] = { W25Q_WRITE_ENABLE, 0x00, 0x00, 0x00 };

    w25qSetBlockProtect(0x00);

    W25Q_CS_LO();
    HAL_SPI_Transmit(W25Q_SPI, temp, 1, 100);
    W25Q_CS_HI();

    temp[0] = W25Q_PAGE_PROGRAM;
    temp[1] = (uint8_t) (pagenum >> 8);
    temp[2] = (uint8_t) (pagenum & 0x00FF);
    temp[3] = 0x00;

    W25Q_CS_LO();
    HAL_SPI_Transmit(W25Q_SPI, temp, 4, 100);
    HAL_SPI_Transmit(W25Q_SPI, page, W25Q_PAGE_LEN, 100);
    W25Q_CS_HI();

    w25qWaitForReady();

    temp[0] = W25Q_WRRITE_DISABLE;

    W25Q_CS_LO();
    HAL_SPI_Transmit(W25Q_SPI, temp, 1, 100);
    W25Q_CS_HI();

    w25qSetBlockProtect(0x0F);

}

void w25qEraseSector(uint16_t sector) {
    w25qSetBlockProtect(0x00);

    sector = (sector << 1);
    uint8_t com = W25Q_WRITE_ENABLE;
    uint8_t temp[4] = { W25Q_SECTOR_ERASE_4, (uint8_t) (sector >> 8),
            (uint8_t) (sector & 0x00FF), 0x00 };
    W25Q_CS_LO();

    HAL_SPI_Transmit(W25Q_SPI, &com, 1, 100);
    W25Q_CS_HI();

    W25Q_CS_LO();

    HAL_SPI_Transmit(W25Q_SPI, temp, 4, 100);
    W25Q_CS_HI();

    w25qWaitForReady();

    temp[0] = W25Q_WRRITE_DISABLE;

    W25Q_CS_LO();
    HAL_SPI_Transmit(W25Q_SPI, temp, 1, 100);
    W25Q_CS_HI();

    w25qSetBlockProtect(0x0F);
}

void w25qWritingByUSB(uint16_t dpagenum, uint8_t *bufByUSB) {

    uint8_t current_sector_buf[4096];
    uint16_t current_sector_addr = dpagenum / 8;
    uint16_t startPage = current_sector_addr * 16;
    int offset = 512 * (dpagenum % 8);

    for (int i = 0; i < 16; i++) {
        w25qReadPage(current_sector_buf + 256 * i, startPage);
        startPage++;
    }

    memcpy(current_sector_buf + offset, bufByUSB, 512);

    w25qEraseSector(current_sector_addr);

    startPage = current_sector_addr * 16;

    for (int i = 0; i < 16; i++) {
        uint8_t buf[256];
        memcpy(buf, current_sector_buf + i * 256, 256);
        w25qWritePage(buf, startPage);
        startPage++;
    }
}

MSC_MEDIA_PACKET 512
USBD_MAX_STR_DESC_SIZ 512

_Min_Heap_Size = 0x400
_Min_Stack_Size = 0x800

I have already despaired and don’t know what the problem is. The flash drive is formatted, but when reconnected, it erases all the data that was on it and again asks for formatting.
Maybe I made a mistake in the functions somewhere and don’t see it? Help me please!

Best Answer

I did it! It works!

#define STORAGE_BLK_NBR      0x4000
#define STORAGE_BLK_SIZ        0x200

int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr,
        uint16_t blk_len) {
    w25qReadPage(buf, blk_addr * 2);
    w25qReadPage(buf + 256, blk_addr * 2 + 1);

    return (USBD_OK);
}

int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr,
        uint16_t blk_len) {
    w25qWritingByUSB(blk_addr, buf);
    return (USBD_OK);
}


void w25qReadPage(uint8_t *page, uint16_t pagenum) {

    uint8_t com[5] = { W25Q_READ_PAGE, (uint8_t) (pagenum >> 8),
            (uint8_t) (pagenum & 0x00FF), 0x00, 0x00 };

    W25Q_CS_LO();

    HAL_SPI_Transmit(W25Q_SPI, com, 5, 10);

    HAL_SPI_Receive(W25Q_SPI, page, W25Q_PAGE_LEN, 10);
    W25Q_CS_HI();
}

void w25qWritePage(uint8_t *page, uint16_t pagenum) {

    uint8_t temp[4] = { W25Q_WRITE_ENABLE, 0x00, 0x00, 0x00 };

    w25qSetBlockProtect(0x00);

    W25Q_CS_LO();
    HAL_SPI_Transmit(W25Q_SPI, temp, 1, 10);
    W25Q_CS_HI();

    temp[0] = W25Q_PAGE_PROGRAM;
    temp[1] = (uint8_t) (pagenum >> 8);
    temp[2] = (uint8_t) (pagenum & 0x00FF);
    temp[3] = 0x00;

    W25Q_CS_LO();
    HAL_SPI_Transmit(W25Q_SPI, temp, 4, 100);
    HAL_SPI_Transmit(W25Q_SPI, page, W25Q_PAGE_LEN, 10);
    W25Q_CS_HI();

    w25qWaitForReady();

    temp[0] = W25Q_WRRITE_DISABLE;

    W25Q_CS_LO();
    HAL_SPI_Transmit(W25Q_SPI, temp, 1, 10);
    W25Q_CS_HI();

    w25qSetBlockProtect(0x0F);

}

void w25qEraseSector(uint32_t sector) {
    w25qSetBlockProtect(0x00);

    sector = (sector << 4);

    uint8_t com = W25Q_WRITE_ENABLE;
    uint8_t temp[4] = { W25Q_SECTOR_ERASE_4, (uint8_t) (sector >> 8),
            (uint8_t) (sector & 0x00FF), 0x00 };

    W25Q_CS_LO();
    HAL_SPI_Transmit(W25Q_SPI, &com, 1, 10);
    W25Q_CS_HI();

    W25Q_CS_LO();
    HAL_SPI_Transmit(W25Q_SPI, temp, 4, 10);
    W25Q_CS_HI();

    w25qWaitForReady();

    temp[0] = W25Q_WRRITE_DISABLE;

    W25Q_CS_LO();
    HAL_SPI_Transmit(W25Q_SPI, temp, 1, 10);
    W25Q_CS_HI();

    w25qSetBlockProtect(0x0F);
}

void w25qWritingByUSB(uint16_t dpagenum, uint8_t *bufByUSB) {

    uint8_t current_sector_buf[4096];
    uint16_t current_sector_addr = dpagenum / 8;
    uint16_t startPage = current_sector_addr * 16;
    int offset = 512 * (dpagenum % 8);

    for (uint16_t i = 0; i < 16; i++) {
        w25qReadPage(current_sector_buf + 256 * i, startPage + i);
    }

    memcpy(current_sector_buf + offset, bufByUSB, 512);

    w25qEraseSector(current_sector_addr);

    startPage = current_sector_addr * 16;

    for (uint16_t i = 0; i < 16; i++) {
        uint8_t buf[256];
        memcpy(buf, current_sector_buf + i * 256, 256);
        w25qWritePage(buf, startPage + i);
    }
}[

MSC_MEDIA_PACKET 512
USBD_MAX_STR_DESC_SIZ 512