1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-01-17 05:32:45 +01:00

drivers/nvram_spi: adapted to SPI API changes

This commit is contained in:
Hauke Petersen 2016-11-08 18:44:44 +01:00
parent ac482fd3e2
commit 8ff20d1386
4 changed files with 53 additions and 100 deletions

View File

@ -38,6 +38,8 @@ extern "C" {
typedef struct nvram_spi_params {
/** @brief RIOT SPI device */
spi_t spi;
/** @brief SPI clock speed */
spi_clk_t clk;
/** @brief Chip select pin */
gpio_t cs;
/** @brief Number of address bytes following each read/write command. */

View File

@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 Eistec AB
* 2016 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License v2.1. See the file LICENSE in the top level directory for more
@ -27,6 +28,7 @@
* - Cypress/Ramtron FM25L04B.
*
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
*/
typedef enum {
@ -114,8 +116,9 @@ int nvram_spi_init(nvram_t *dev, nvram_spi_params_t *spi_params, size_t size)
}
dev->extra = spi_params;
gpio_init(spi_params->cs, GPIO_OUT);
gpio_set(spi_params->cs);
if (spi_init_cs(spi_params->spi, spi_params->cs) != SPI_OK) {
return -1;
}
return 0;
}
@ -123,54 +126,37 @@ int nvram_spi_init(nvram_t *dev, nvram_spi_params_t *spi_params, size_t size)
static int nvram_spi_write(nvram_t *dev, const uint8_t *src, uint32_t dst, size_t len)
{
nvram_spi_params_t *spi_dev = (nvram_spi_params_t *) dev->extra;
int status;
union {
uint32_t u32;
char c[4];
} addr;
/* Address is expected by the device as big-endian, i.e. network byte order,
* we utilize the network byte order macros here. */
addr.u32 = HTONL(dst);
/* Acquire exclusive bus access */
spi_acquire(spi_dev->spi);
/* Assert CS */
gpio_clear(spi_dev->cs);
/* Acquire exclusive bus access while configuring clock and mode */
spi_acquire(spi_dev->spi, spi_dev->cs, SPI_MODE_0, spi_dev->clk);
/* Enable writes */
status = spi_transfer_byte(spi_dev->spi, NVRAM_SPI_CMD_WREN, NULL);
if (status < 0)
{
return status;
}
/* Release CS */
gpio_set(spi_dev->cs);
spi_transfer_byte(spi_dev->spi, spi_dev->cs, false, NVRAM_SPI_CMD_WREN);
/* Make sure we have a minimum gap between transfers */
xtimer_spin(NVRAM_SPI_CS_TOGGLE_TICKS);
/* Re-assert CS */
gpio_clear(spi_dev->cs);
/* Write command and address */
status = spi_transfer_regs(spi_dev->spi, NVRAM_SPI_CMD_WRITE,
spi_transfer_byte(spi_dev->spi, spi_dev->cs, true, NVRAM_SPI_CMD_WRITE);
spi_transfer_bytes(spi_dev->spi, spi_dev->cs, true,
&addr.c[sizeof(addr.c) - spi_dev->address_count], NULL,
spi_dev->address_count);
if (status < 0)
{
return status;
}
/* Keep holding CS and write data */
status = spi_transfer_bytes(spi_dev->spi, (char *)src, NULL, len);
if (status < 0)
{
return status;
}
/* Release CS */
gpio_set(spi_dev->cs);
/* Write data (we still hold the CS line low in between) */
spi_transfer_bytes(spi_dev->spi, spi_dev->cs, false, src, NULL, len);
/* Release exclusive bus access */
spi_release(spi_dev->spi);
return status;
return (int)len;
}
static int nvram_spi_read(nvram_t *dev, uint8_t *dst, uint32_t src, size_t len)
{
nvram_spi_params_t *spi_dev = (nvram_spi_params_t *) dev->extra;
int status;
union {
uint32_t u32;
char c[4];
@ -178,40 +164,31 @@ static int nvram_spi_read(nvram_t *dev, uint8_t *dst, uint32_t src, size_t len)
/* Address is expected by the device as big-endian, i.e. network byte order,
* we utilize the network byte order macros here. */
addr.u32 = HTONL(src);
/* Acquire exclusive bus access */
spi_acquire(spi_dev->spi);
/* Assert CS */
gpio_clear(spi_dev->cs);
/* Acquire exclusive bus access while configuring clock and mode */
spi_acquire(spi_dev->spi, spi_dev->cs, SPI_MODE_0, spi_dev->clk);
/* Write command and address */
status = spi_transfer_regs(spi_dev->spi, NVRAM_SPI_CMD_READ,
spi_transfer_byte(spi_dev->spi, spi_dev->cs, true, NVRAM_SPI_CMD_READ);
spi_transfer_bytes(spi_dev->spi, spi_dev->cs, true,
&addr.c[sizeof(addr.c) - spi_dev->address_count],
NULL, spi_dev->address_count);
if (status < 0)
{
return status;
}
/* Keep holding CS and read data */
status = spi_transfer_bytes(spi_dev->spi, NULL, (char *)dst, len);
if (status < 0)
{
return status;
}
/* Release CS */
gpio_set(spi_dev->cs);
/* Read data (while still holding the CS line active) */
spi_transfer_bytes(spi_dev->spi, spi_dev->cs, false, NULL, dst, len);
/* Release exclusive bus access */
spi_release(spi_dev->spi);
/* status contains the number of bytes actually read from the SPI bus. */
return status;
return (int)len;
}
static int nvram_spi_write_9bit_addr(nvram_t *dev, const uint8_t *src, uint32_t dst, size_t len)
{
nvram_spi_params_t *spi_dev = (nvram_spi_params_t *) dev->extra;
int status;
uint8_t cmd;
uint8_t addr;
cmd = NVRAM_SPI_CMD_WRITE;
/* The upper address bit is mixed into the command byte on certain devices,
* probably just to save a byte in the SPI transfer protocol. */
if (dst > 0xff) {
@ -219,42 +196,30 @@ static int nvram_spi_write_9bit_addr(nvram_t *dev, const uint8_t *src, uint32_t
}
/* LSB of address */
addr = (dst & 0xff);
spi_acquire(spi_dev->spi);
gpio_clear(spi_dev->cs);
spi_acquire(spi_dev->spi, spi_dev->cs, SPI_MODE_0, spi_dev->clk);
/* Enable writes */
status = spi_transfer_byte(spi_dev->spi, NVRAM_SPI_CMD_WREN, NULL);
if (status < 0)
{
return status;
}
gpio_set(spi_dev->cs);
spi_transfer_byte(spi_dev->spi, spi_dev->cs, false, NVRAM_SPI_CMD_WREN);
/* Insert needed delay between transactions */
xtimer_spin(NVRAM_SPI_CS_TOGGLE_TICKS);
gpio_clear(spi_dev->cs);
/* Write command and address */
status = spi_transfer_reg(spi_dev->spi, cmd, addr, NULL);
if (status < 0)
{
return status;
}
spi_transfer_byte(spi_dev->spi, spi_dev->cs, true, cmd);
spi_transfer_byte(spi_dev->spi, spi_dev->cs, true, addr);
/* Keep holding CS and write data */
status = spi_transfer_bytes(spi_dev->spi, (char *)src, NULL, len);
if (status < 0)
{
return status;
}
gpio_set(spi_dev->cs);
spi_transfer_bytes(spi_dev->spi, spi_dev->cs, false, src, NULL, len);
spi_release(spi_dev->spi);
/* status contains the number of bytes actually written to the SPI bus. */
return status;
return (int)len;
}
static int nvram_spi_read_9bit_addr(nvram_t *dev, uint8_t *dst, uint32_t src, size_t len)
{
nvram_spi_params_t *spi_dev = (nvram_spi_params_t *) dev->extra;
int status;
uint8_t cmd;
uint8_t addr;
cmd = NVRAM_SPI_CMD_READ;
/* The upper address bit is mixed into the command byte on certain devices,
* probably just to save a byte in the SPI transfer protocol. */
if (src > 0xff) {
@ -262,24 +227,17 @@ static int nvram_spi_read_9bit_addr(nvram_t *dev, uint8_t *dst, uint32_t src, si
}
/* LSB of address */
addr = (src & 0xff);
spi_acquire(spi_dev->spi);
gpio_clear(spi_dev->cs);
spi_acquire(spi_dev->spi, spi_dev->cs, SPI_MODE_0, spi_dev->clk);
/* Write command and address */
status = spi_transfer_reg(spi_dev->spi, (char)cmd, addr, NULL);
if (status < 0)
{
return status;
}
spi_transfer_byte(spi_dev->spi, spi_dev->cs, true, cmd);
spi_transfer_byte(spi_dev->spi, spi_dev->cs, true, addr);
/* Keep holding CS and read data */
status = spi_transfer_bytes(spi_dev->spi, NULL, (char *)dst, len);
if (status < 0)
{
return status;
}
gpio_set(spi_dev->cs);
spi_transfer_bytes(spi_dev->spi, spi_dev->cs, false, NULL, dst, len);
spi_release(spi_dev->spi);
/* status contains the number of bytes actually read from the SPI bus. */
return status;
return (int)len;
}
/** @} */

View File

@ -7,7 +7,7 @@ USEMODULE += nvram_spi
USEMODULE += xtimer
# set default device parameters in case they are undefined
TEST_NVRAM_SPI_DEV ?= SPI_0
TEST_NVRAM_SPI_DEV ?= SPI_DEV\(0\)
TEST_NVRAM_SPI_CS ?= GPIO_PIN\(0,0\)
TEST_NVRAM_SPI_SIZE ?= 64
TEST_NVRAM_SPI_ADDRESS_COUNT ?= 1

View File

@ -40,16 +40,16 @@
#error "TEST_NVRAM_SPI_ADDRESS_COUNT not defined"
#endif
#ifdef TEST_NVRAM_SPI_CONF
#define SPI_CONF (TEST_NVRAM_SPI_CONF)
#ifdef TEST_NVRAM_SPI_MODE
#define SPI_MODE (TEST_NVRAM_SPI_MODE)
#else
#define SPI_CONF (SPI_CONF_FIRST_RISING)
#define SPI_MODE (SPI_MODE_0)
#endif
#ifdef TEST_NVRAM_SPI_SPEED
#define SPI_SPEED (TEST_NVRAM_SPI_SPEED)
#define SPI_CLK (TEST_NVRAM_SPI_SPEED)
#else
#define SPI_SPEED (SPI_SPEED_10MHZ)
#define SPI_CLK (SPI_CLK_10MHZ)
#endif
/* This will only work on small memories. Modify if you need to test NVRAM
@ -114,6 +114,7 @@ int main(void)
uint32_t i;
nvram_spi_params_t spi_params = {
.spi = TEST_NVRAM_SPI_DEV,
.clk = SPI_CLK,
.cs = TEST_NVRAM_SPI_CS,
.address_count = TEST_NVRAM_SPI_ADDRESS_COUNT,
};
@ -121,14 +122,6 @@ int main(void)
uint32_t start_delay = 10;
puts("NVRAM SPI test application starting...");
printf("Initializing SPI_%i... ", TEST_NVRAM_SPI_DEV);
if (spi_init_master(TEST_NVRAM_SPI_DEV, SPI_CONF, SPI_SPEED_10MHZ) == 0) {
puts("[OK]");
}
else {
puts("[Failed]\n");
return 1;
}
puts("Initializing NVRAM SPI device descriptor... ");
if (nvram_spi_init(&dev, &spi_params, TEST_NVRAM_SPI_SIZE) == 0) {