W25Q80BV: Consolidate API to perform entire transfers in one call.

This commit is contained in:
Jared Boone
2014-11-04 18:26:09 -08:00
parent 8edeaaa21e
commit 6668c2706b
3 changed files with 75 additions and 63 deletions

View File

@ -31,6 +31,8 @@
#include "w25q80bv.h"
#include "w25q80bv_drv.h"
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
#define W25Q80BV_WRITE_ENABLE 0x06
#define W25Q80BV_CHIP_ERASE 0xC7
#define W25Q80BV_READ_STATUS1 0x05
@ -55,7 +57,7 @@ void w25q80bv_setup(w25q80bv_driver_t* const drv)
drv->num_pages = 4096U;
drv->num_bytes = 1048576U;
w25q80bv_spi_init(drv->hw);
w25q80bv_hw_init(drv->hw);
device_id = 0;
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 value;
w25q80bv_spi_select(drv->hw);
w25q80bv_spi_transfer(drv->hw, W25Q80BV_READ_STATUS1);
value = w25q80bv_spi_transfer(drv->hw, 0xFF);
w25q80bv_spi_unselect(drv->hw);
return value;
uint8_t data[] = { W25Q80BV_READ_STATUS1, 0xFF };
w25q80bv_hw_transfer(drv->hw, data, ARRAY_SIZE(data));
return data[1];
}
/* Release power down / Device ID */
uint8_t w25q80bv_get_device_id(w25q80bv_driver_t* const drv)
{
uint8_t value;
w25q80bv_spi_select(drv->hw);
w25q80bv_spi_transfer(drv->hw, W25Q80BV_DEVICE_ID);
/* Read 3 dummy bytes */
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;
uint8_t data[] = {
W25Q80BV_DEVICE_ID,
0xFF, 0xFF, 0xFF, 0xFF
};
w25q80bv_hw_transfer(drv->hw, data, ARRAY_SIZE(data));
return data[4];
}
void w25q80bv_get_unique_id(w25q80bv_driver_t* const drv, w25q80bv_unique_id_t* unique_id)
{
int i;
uint8_t value;
uint8_t data[] = {
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);
w25q80bv_spi_transfer(drv->hw, W25Q80BV_UNIQUE_ID);
/* 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;
for(size_t i=0; i<8; i++) {
unique_id->id_8b[i] = data[5+i];
}
w25q80bv_spi_unselect(drv->hw);
}
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)
{
w25q80bv_wait_while_busy(drv);
w25q80bv_spi_select(drv->hw);
w25q80bv_spi_transfer(drv->hw, W25Q80BV_WRITE_ENABLE);
w25q80bv_spi_unselect(drv->hw);
uint8_t data[] = { W25Q80BV_WRITE_ENABLE };
w25q80bv_hw_transfer(drv->hw, data, ARRAY_SIZE(data));
}
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_wait_while_busy(drv);
w25q80bv_spi_select(drv->hw);
w25q80bv_spi_transfer(drv->hw, W25Q80BV_CHIP_ERASE);
w25q80bv_spi_unselect(drv->hw);
uint8_t data[] = { W25Q80BV_CHIP_ERASE };
w25q80bv_hw_transfer(drv->hw, data, ARRAY_SIZE(data));
}
/* 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 */
if (((addr & 0xFF) + len) > drv->page_len)
return;
@ -164,14 +142,19 @@ void w25q80bv_page_program(w25q80bv_driver_t* const drv, const uint32_t addr, co
w25q80bv_write_enable(drv);
w25q80bv_wait_while_busy(drv);
w25q80bv_spi_select(drv->hw);
w25q80bv_spi_transfer(drv->hw, W25Q80BV_PAGE_PROGRAM);
w25q80bv_spi_transfer(drv->hw, (addr & 0xFF0000) >> 16);
w25q80bv_spi_transfer(drv->hw, (addr & 0xFF00) >> 8);
w25q80bv_spi_transfer(drv->hw, addr & 0xFF);
for (i = 0; i < len; i++)
w25q80bv_spi_transfer(drv->hw, data[i]);
w25q80bv_spi_unselect(drv->hw);
uint8_t header[] = {
W25Q80BV_PAGE_PROGRAM,
(addr & 0xFF0000) >> 16,
(addr & 0xFF00) >> 8,
addr & 0xFF
};
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 */

View File

@ -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);
}
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 clock_prescale_rate = 2;
@ -89,3 +89,24 @@ void w25q80bv_spi_init(w25q80bv_hw_t* const hw) {
SSP_MASTER,
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);
}

View File

@ -25,15 +25,23 @@
#define __W25Q80BV_DRV_H__
#include <stdint.h>
#include <stddef.h>
typedef struct {
uint8_t* const data;
const size_t count;
} w25q80bv_transfer_t;
typedef struct {
/* Empty for now */
} w25q80bv_hw_t;
void w25q80bv_spi_init(w25q80bv_hw_t* const hw);
void w25q80bv_spi_select(w25q80bv_hw_t* const hw);
uint16_t w25q80bv_spi_transfer(w25q80bv_hw_t* const hw, const uint16_t tx_data);
void w25q80bv_spi_unselect(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_hw_transfer_multiple(
w25q80bv_hw_t* const hw,
const w25q80bv_transfer_t* const transfers,
const size_t transfer_count
);
#endif//__W25Q80BV_DRV_H__