W25Q80BV: Consolidate API to perform entire transfers in one call.
This commit is contained in:
@ -31,6 +31,8 @@
|
|||||||
#include "w25q80bv.h"
|
#include "w25q80bv.h"
|
||||||
#include "w25q80bv_drv.h"
|
#include "w25q80bv_drv.h"
|
||||||
|
|
||||||
|
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||||
|
|
||||||
#define W25Q80BV_WRITE_ENABLE 0x06
|
#define W25Q80BV_WRITE_ENABLE 0x06
|
||||||
#define W25Q80BV_CHIP_ERASE 0xC7
|
#define W25Q80BV_CHIP_ERASE 0xC7
|
||||||
#define W25Q80BV_READ_STATUS1 0x05
|
#define W25Q80BV_READ_STATUS1 0x05
|
||||||
@ -55,7 +57,7 @@ void w25q80bv_setup(w25q80bv_driver_t* const drv)
|
|||||||
drv->num_pages = 4096U;
|
drv->num_pages = 4096U;
|
||||||
drv->num_bytes = 1048576U;
|
drv->num_bytes = 1048576U;
|
||||||
|
|
||||||
w25q80bv_spi_init(drv->hw);
|
w25q80bv_hw_init(drv->hw);
|
||||||
|
|
||||||
device_id = 0;
|
device_id = 0;
|
||||||
while(device_id != W25Q80BV_DEVICE_ID_RES)
|
while(device_id != W25Q80BV_DEVICE_ID_RES)
|
||||||
@ -66,56 +68,34 @@ void w25q80bv_setup(w25q80bv_driver_t* const drv)
|
|||||||
|
|
||||||
uint8_t w25q80bv_get_status(w25q80bv_driver_t* const drv)
|
uint8_t w25q80bv_get_status(w25q80bv_driver_t* const drv)
|
||||||
{
|
{
|
||||||
uint8_t value;
|
uint8_t data[] = { W25Q80BV_READ_STATUS1, 0xFF };
|
||||||
|
w25q80bv_hw_transfer(drv->hw, data, ARRAY_SIZE(data));
|
||||||
w25q80bv_spi_select(drv->hw);
|
return data[1];
|
||||||
w25q80bv_spi_transfer(drv->hw, W25Q80BV_READ_STATUS1);
|
|
||||||
value = w25q80bv_spi_transfer(drv->hw, 0xFF);
|
|
||||||
w25q80bv_spi_unselect(drv->hw);
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Release power down / Device ID */
|
/* Release power down / Device ID */
|
||||||
uint8_t w25q80bv_get_device_id(w25q80bv_driver_t* const drv)
|
uint8_t w25q80bv_get_device_id(w25q80bv_driver_t* const drv)
|
||||||
{
|
{
|
||||||
uint8_t value;
|
uint8_t data[] = {
|
||||||
|
W25Q80BV_DEVICE_ID,
|
||||||
w25q80bv_spi_select(drv->hw);
|
0xFF, 0xFF, 0xFF, 0xFF
|
||||||
w25q80bv_spi_transfer(drv->hw, W25Q80BV_DEVICE_ID);
|
};
|
||||||
|
w25q80bv_hw_transfer(drv->hw, data, ARRAY_SIZE(data));
|
||||||
/* Read 3 dummy bytes */
|
return data[4];
|
||||||
value = w25q80bv_spi_transfer(drv->hw, 0xFF);
|
|
||||||
value = w25q80bv_spi_transfer(drv->hw, 0xFF);
|
|
||||||
value = w25q80bv_spi_transfer(drv->hw, 0xFF);
|
|
||||||
/* Read Device ID shall return 0x13 for W25Q80BV */
|
|
||||||
value = w25q80bv_spi_transfer(drv->hw, 0xFF);
|
|
||||||
|
|
||||||
w25q80bv_spi_unselect(drv->hw);
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void w25q80bv_get_unique_id(w25q80bv_driver_t* const drv, w25q80bv_unique_id_t* unique_id)
|
void w25q80bv_get_unique_id(w25q80bv_driver_t* const drv, w25q80bv_unique_id_t* unique_id)
|
||||||
{
|
{
|
||||||
int i;
|
uint8_t data[] = {
|
||||||
uint8_t value;
|
W25Q80BV_UNIQUE_ID,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
|
||||||
|
};
|
||||||
|
w25q80bv_hw_transfer(drv->hw, data, ARRAY_SIZE(data));
|
||||||
|
|
||||||
w25q80bv_spi_select(drv->hw);
|
for(size_t i=0; i<8; i++) {
|
||||||
w25q80bv_spi_transfer(drv->hw, W25Q80BV_UNIQUE_ID);
|
unique_id->id_8b[i] = data[5+i];
|
||||||
|
|
||||||
/* Read 4 dummy bytes */
|
|
||||||
for(i=0; i<4; i++)
|
|
||||||
value = w25q80bv_spi_transfer(drv->hw, 0xFF);
|
|
||||||
|
|
||||||
/* Read Unique ID 64bits (8*8) */
|
|
||||||
for(i=0; i<8; i++)
|
|
||||||
{
|
|
||||||
value = w25q80bv_spi_transfer(drv->hw, 0xFF);
|
|
||||||
unique_id->id_8b[i] = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
w25q80bv_spi_unselect(drv->hw);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void w25q80bv_wait_while_busy(w25q80bv_driver_t* const drv)
|
void w25q80bv_wait_while_busy(w25q80bv_driver_t* const drv)
|
||||||
@ -126,9 +106,9 @@ void w25q80bv_wait_while_busy(w25q80bv_driver_t* const drv)
|
|||||||
void w25q80bv_write_enable(w25q80bv_driver_t* const drv)
|
void w25q80bv_write_enable(w25q80bv_driver_t* const drv)
|
||||||
{
|
{
|
||||||
w25q80bv_wait_while_busy(drv);
|
w25q80bv_wait_while_busy(drv);
|
||||||
w25q80bv_spi_select(drv->hw);
|
|
||||||
w25q80bv_spi_transfer(drv->hw, W25Q80BV_WRITE_ENABLE);
|
uint8_t data[] = { W25Q80BV_WRITE_ENABLE };
|
||||||
w25q80bv_spi_unselect(drv->hw);
|
w25q80bv_hw_transfer(drv->hw, data, ARRAY_SIZE(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
void w25q80bv_chip_erase(w25q80bv_driver_t* const drv)
|
void w25q80bv_chip_erase(w25q80bv_driver_t* const drv)
|
||||||
@ -143,16 +123,14 @@ void w25q80bv_chip_erase(w25q80bv_driver_t* const drv)
|
|||||||
|
|
||||||
w25q80bv_write_enable(drv);
|
w25q80bv_write_enable(drv);
|
||||||
w25q80bv_wait_while_busy(drv);
|
w25q80bv_wait_while_busy(drv);
|
||||||
w25q80bv_spi_select(drv->hw);
|
|
||||||
w25q80bv_spi_transfer(drv->hw, W25Q80BV_CHIP_ERASE);
|
uint8_t data[] = { W25Q80BV_CHIP_ERASE };
|
||||||
w25q80bv_spi_unselect(drv->hw);
|
w25q80bv_hw_transfer(drv->hw, data, ARRAY_SIZE(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* write up a 256 byte page or partial page */
|
/* write up a 256 byte page or partial page */
|
||||||
void w25q80bv_page_program(w25q80bv_driver_t* const drv, const uint32_t addr, const uint16_t len, const uint8_t* data)
|
static void w25q80bv_page_program(w25q80bv_driver_t* const drv, const uint32_t addr, const uint16_t len, uint8_t* data)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
|
|
||||||
/* do nothing if asked to write beyond a page boundary */
|
/* do nothing if asked to write beyond a page boundary */
|
||||||
if (((addr & 0xFF) + len) > drv->page_len)
|
if (((addr & 0xFF) + len) > drv->page_len)
|
||||||
return;
|
return;
|
||||||
@ -164,14 +142,19 @@ void w25q80bv_page_program(w25q80bv_driver_t* const drv, const uint32_t addr, co
|
|||||||
w25q80bv_write_enable(drv);
|
w25q80bv_write_enable(drv);
|
||||||
w25q80bv_wait_while_busy(drv);
|
w25q80bv_wait_while_busy(drv);
|
||||||
|
|
||||||
w25q80bv_spi_select(drv->hw);
|
uint8_t header[] = {
|
||||||
w25q80bv_spi_transfer(drv->hw, W25Q80BV_PAGE_PROGRAM);
|
W25Q80BV_PAGE_PROGRAM,
|
||||||
w25q80bv_spi_transfer(drv->hw, (addr & 0xFF0000) >> 16);
|
(addr & 0xFF0000) >> 16,
|
||||||
w25q80bv_spi_transfer(drv->hw, (addr & 0xFF00) >> 8);
|
(addr & 0xFF00) >> 8,
|
||||||
w25q80bv_spi_transfer(drv->hw, addr & 0xFF);
|
addr & 0xFF
|
||||||
for (i = 0; i < len; i++)
|
};
|
||||||
w25q80bv_spi_transfer(drv->hw, data[i]);
|
|
||||||
w25q80bv_spi_unselect(drv->hw);
|
const w25q80bv_transfer_t transfers[] = {
|
||||||
|
{ header, ARRAY_SIZE(header) },
|
||||||
|
{ data, len }
|
||||||
|
};
|
||||||
|
|
||||||
|
w25q80bv_hw_transfer_multiple(drv->hw, transfers, ARRAY_SIZE(transfers));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* write an arbitrary number of bytes */
|
/* write an arbitrary number of bytes */
|
||||||
|
@ -45,7 +45,7 @@ static uint16_t w25q80bv_spi_transfer(w25q80bv_hw_t* const hw, const uint16_t tx
|
|||||||
return ssp_transfer(SSP0_NUM, tx_data);
|
return ssp_transfer(SSP0_NUM, tx_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void w25q80bv_spi_init(w25q80bv_hw_t* const hw) {
|
void w25q80bv_hw_init(w25q80bv_hw_t* const hw) {
|
||||||
const uint8_t serial_clock_rate = 2;
|
const uint8_t serial_clock_rate = 2;
|
||||||
const uint8_t clock_prescale_rate = 2;
|
const uint8_t clock_prescale_rate = 2;
|
||||||
|
|
||||||
@ -89,3 +89,24 @@ void w25q80bv_spi_init(w25q80bv_hw_t* const hw) {
|
|||||||
SSP_MASTER,
|
SSP_MASTER,
|
||||||
SSP_SLAVE_OUT_ENABLE);
|
SSP_SLAVE_OUT_ENABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void w25q80bv_hw_transfer_multiple(
|
||||||
|
w25q80bv_hw_t* const hw,
|
||||||
|
const w25q80bv_transfer_t* const transfers,
|
||||||
|
const size_t transfer_count
|
||||||
|
) {
|
||||||
|
w25q80bv_spi_select(hw);
|
||||||
|
for(size_t i=0; i<transfer_count; i++) {
|
||||||
|
for(size_t j=0; j<transfers[i].count; j++) {
|
||||||
|
transfers[i].data[j] = w25q80bv_spi_transfer(hw, transfers[i].data[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
w25q80bv_spi_unselect(hw);
|
||||||
|
}
|
||||||
|
|
||||||
|
void w25q80bv_hw_transfer(w25q80bv_hw_t* const hw, uint8_t* data, const size_t count) {
|
||||||
|
const w25q80bv_transfer_t transfer = {
|
||||||
|
data, count
|
||||||
|
};
|
||||||
|
w25q80bv_hw_transfer_multiple(hw, &transfer, 1);
|
||||||
|
}
|
||||||
|
@ -25,15 +25,23 @@
|
|||||||
#define __W25Q80BV_DRV_H__
|
#define __W25Q80BV_DRV_H__
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t* const data;
|
||||||
|
const size_t count;
|
||||||
|
} w25q80bv_transfer_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/* Empty for now */
|
/* Empty for now */
|
||||||
} w25q80bv_hw_t;
|
} w25q80bv_hw_t;
|
||||||
|
|
||||||
void w25q80bv_spi_init(w25q80bv_hw_t* const hw);
|
void w25q80bv_hw_init(w25q80bv_hw_t* const hw);
|
||||||
|
void w25q80bv_hw_transfer(w25q80bv_hw_t* const hw, uint8_t* data, const size_t count);
|
||||||
void w25q80bv_spi_select(w25q80bv_hw_t* const hw);
|
void w25q80bv_hw_transfer_multiple(
|
||||||
uint16_t w25q80bv_spi_transfer(w25q80bv_hw_t* const hw, const uint16_t tx_data);
|
w25q80bv_hw_t* const hw,
|
||||||
void w25q80bv_spi_unselect(w25q80bv_hw_t* const hw);
|
const w25q80bv_transfer_t* const transfers,
|
||||||
|
const size_t transfer_count
|
||||||
|
);
|
||||||
|
|
||||||
#endif//__W25Q80BV_DRV_H__
|
#endif//__W25Q80BV_DRV_H__
|
||||||
|
Reference in New Issue
Block a user