parent
19bd043ac3
commit
b6d216255f
@ -1,23 +0,0 @@ |
||||
#pragma once |
||||
|
||||
/* Read commands */ |
||||
#define CMD_READ_ARRAY_SLOW 0x03 |
||||
#define CMD_READ_ID 0x9f |
||||
|
||||
/* Write commands */ |
||||
#define CMD_PAGE_PROGRAM 0x02 |
||||
#define CMD_WRITE_DISABLE 0x04 |
||||
#define CMD_WRITE_ENABLE 0x06 |
||||
|
||||
/* Erase commands */ |
||||
#define CMD_ERASE_4K 0x20 |
||||
#define CMD_ERASE_32K 0x52 |
||||
#define CMD_ERASE_64K 0xD8 |
||||
#define CMD_ERASE_CHIP 0x60 |
||||
|
||||
void init_spi(void); |
||||
void spi_send_cmd(uint32_t dev, const char *cmd, size_t cmd_len, |
||||
char *data, size_t data_len); |
||||
void spi_flash_read(uint32_t dev, uint32_t addr, char *data, size_t len); |
||||
void spi_flash_write(uint32_t dev, uint32_t addr, char *data, size_t len); |
||||
void spi_flash_erase(uint32_t dev, uint32_t addr, size_t len); |
@ -1,155 +0,0 @@ |
||||
#define _GNU_SOURCE |
||||
#include <libopencm3/stm32/rcc.h> |
||||
#include <libopencm3/stm32/gpio.h> |
||||
#include <libopencm3/stm32/spi.h> |
||||
#include <libopencm3/stm32/usart.h> |
||||
|
||||
#include <ctype.h> |
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
#include <errno.h> |
||||
#include <stddef.h> |
||||
#include <limits.h> |
||||
#include <sys/types.h> |
||||
|
||||
#include <macros.h> |
||||
#include <spi_flash.h> |
||||
|
||||
void init_spi(void) |
||||
{ |
||||
/* Set up clocks for SPI 1 */ |
||||
rcc_clock_setup_in_hsi_out_48mhz(); |
||||
rcc_periph_clock_enable(RCC_GPIOA); |
||||
rcc_periph_clock_enable(RCC_GPIOB); |
||||
rcc_periph_clock_enable(RCC_SPI1); |
||||
|
||||
/* Set up GPIOs for SPI 1 */ |
||||
gpio_mode_setup(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO4); |
||||
gpio_set(GPIOA, GPIO4); |
||||
gpio_mode_setup(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO3 | GPIO4 | GPIO5); |
||||
gpio_set_af(GPIOB, GPIO_AF0, GPIO3 | GPIO4 | GPIO5); |
||||
|
||||
spi_set_master_mode(SPI1); |
||||
spi_set_baudrate_prescaler(SPI1, SPI_CR1_BR_FPCLK_DIV_64); |
||||
spi_set_clock_polarity_0(SPI1); |
||||
spi_set_clock_phase_0(SPI1); |
||||
spi_set_full_duplex_mode(SPI1); |
||||
spi_set_unidirectional_mode(SPI1); /* bidirectional but in 3-wire */ |
||||
spi_set_data_size(SPI1, SPI_CR2_DS_8BIT); |
||||
spi_enable_software_slave_management(SPI1); |
||||
spi_send_msb_first(SPI1); |
||||
spi_set_nss_high(SPI1); |
||||
spi_fifo_reception_threshold_8bit(SPI1); |
||||
SPI_I2SCFGR(SPI1) &= ~SPI_I2SCFGR_I2SMOD; |
||||
spi_enable(SPI1); |
||||
} |
||||
|
||||
void spi_send_cmd(uint32_t dev, const char *cmd, size_t cmd_len, |
||||
char *data, size_t data_len) |
||||
{ |
||||
size_t i; |
||||
|
||||
gpio_clear(GPIOA, GPIO4); |
||||
|
||||
for (i = 0; i < cmd_len; ++i) { |
||||
spi_send8(dev, *cmd++); |
||||
(void)spi_read8(dev); |
||||
} |
||||
|
||||
for (i = 0; i < data_len; ++i) { |
||||
spi_send8(dev, 0); |
||||
*data++ = spi_read8(dev); |
||||
} |
||||
|
||||
gpio_set(GPIOA, GPIO4); |
||||
} |
||||
|
||||
static void spi_flash_addr(char *cmd, uint32_t addr) |
||||
{ |
||||
cmd[1] = addr >> 16; |
||||
cmd[2] = addr >> 8; |
||||
cmd[3] = addr; |
||||
} |
||||
|
||||
static void spi_enable_write(uint32_t dev) |
||||
{ |
||||
char cmd[1] = { CMD_WRITE_ENABLE }; |
||||
|
||||
spi_send_cmd(dev, cmd, 1, NULL, 0); |
||||
} |
||||
|
||||
static void spi_disable_write(uint32_t dev) |
||||
{ |
||||
char cmd[1] = { CMD_WRITE_DISABLE }; |
||||
|
||||
spi_send_cmd(dev, cmd, 1, NULL, 0); |
||||
} |
||||
|
||||
void spi_flash_read(uint32_t dev, uint32_t addr, char *data, size_t len) |
||||
{ |
||||
char cmd[4] = { CMD_READ_ARRAY_SLOW }; |
||||
|
||||
spi_flash_addr(cmd, addr); |
||||
spi_send_cmd(dev, cmd, 4, data, len); |
||||
} |
||||
|
||||
void spi_flash_write(uint32_t dev, uint32_t addr, char *data, size_t len) |
||||
{ |
||||
char cmd[4] = { CMD_PAGE_PROGRAM }; |
||||
size_t i; |
||||
|
||||
spi_enable_write(dev); |
||||
spi_flash_addr(cmd, addr); |
||||
|
||||
gpio_clear(GPIOA, GPIO4); |
||||
|
||||
for (i = 0; i < 4; ++i) { |
||||
spi_send8(dev, cmd[i]); |
||||
(void)spi_read8(dev); |
||||
} |
||||
|
||||
for (i = 0; i < len; ++i) { |
||||
spi_send8(dev, data[i]); |
||||
(void)spi_read8(dev); |
||||
} |
||||
|
||||
gpio_set(GPIOA, GPIO4); |
||||
|
||||
spi_disable_write(dev); |
||||
} |
||||
|
||||
void spi_flash_erase(uint32_t dev, uint32_t addr, size_t len) |
||||
{ |
||||
char cmd[4]; |
||||
size_t size; |
||||
|
||||
spi_enable_write(dev); |
||||
|
||||
addr = ROUND_UP(addr, 4 * KIB); |
||||
|
||||
for (; len; addr += size, len -= size) { |
||||
if (IS_ROUND(addr, 64 * KIB) && IS_ROUND(len, 64 * KIB)) |
||||
size = 64 * KIB; |
||||
else if (IS_ROUND(addr, 32 * KIB) && IS_ROUND(len, 32 * KIB)) |
||||
size = 32 * KIB; |
||||
else if (IS_ROUND(addr, 4 * KIB) && IS_ROUND(len, 4 * KIB)) |
||||
size = 4 * KIB; |
||||
else |
||||
size = 0; |
||||
|
||||
switch (size) { |
||||
case 64 * KIB: cmd[0] = CMD_ERASE_64K; break; |
||||
case 32 * KIB: cmd[0] = CMD_ERASE_32K; break; |
||||
case 4 * KIB: cmd[0] = CMD_ERASE_4K; break; |
||||
default: goto err_disable_write; |
||||
}; |
||||
|
||||
printf("addr: %lx; size: %u\n", addr, size); |
||||
spi_flash_addr(cmd, addr); |
||||
spi_send_cmd(dev, cmd, 4, NULL, 0); |
||||
} |
||||
|
||||
err_disable_write: |
||||
spi_disable_write(dev); |
||||
} |
Loading…
Reference in new issue