вот #include "spiflash.h"
#include "systime.h"
#include "stm32f4xx.h"
#include <string.h>
static bool busy = false;
static uint8_t volatile dmabuf[260];
static int addr_delayed, len_delayed;
static const uint8_t* src_delayed;
static void
cs_assert(void)
{
GPIOD->BSRR = 1 << (2 + 16);
}
static void
cs_deassert(void)
{
GPIOD->BSRR = 1 << 2;
systime_delay(SYSTIME_TPS / 10000000);
}
void
spiflash_init(void)
{
// configure SCK, MOSI, MISO
GPIOC->AFR[1] |= (6 << ((10 - 8) * 4))
| (6 << ((11 - 8) * 4))
| (6 << ((12 - 8) * 4));
GPIOC->MODER |= GPIO_MODER_MODER10_1
| GPIO_MODER_MODER11_1
| GPIO_MODER_MODER12_1;
// configure NSS
cs_deassert();
GPIOD->MODER |= GPIO_MODER_MODER2_0;
SPI3->CR2 = SPI_CR2_TXDMAEN
| SPI_CR2_RXDMAEN;
SPI3->CR1 = SPI_CR1_SSM
| SPI_CR1_SSI
| SPI_CR1_SPE
| SPI_CR1_MSTR;
}
static void
transfer(int len)
{
static DMA_TypeDef* const dma = DMA1;
static DMA_Stream_TypeDef* const rx_stream = DMA1_Stream0;
static DMA_Stream_TypeDef* const tx_stream = DMA1_Stream7;
rx_stream->M0AR = (int)dmabuf;
tx_stream->M0AR = (int)dmabuf;
rx_stream->PAR = (int)&SPI3->DR;
tx_stream->PAR = (int)&SPI3->DR;
rx_stream->NDTR = len;
tx_stream->NDTR = len;
rx_stream->CR = (0 * DMA_SxCR_CHSEL_0) // select channel
| DMA_SxCR_MINC; // memory increment mode
rx_stream->CR |= DMA_SxCR_EN; // enable stream
tx_stream->CR = (0 * DMA_SxCR_CHSEL_0) // select channel
| DMA_SxCR_DIR_0 // memory to peripheral
| DMA_SxCR_MINC; // memory increment mode
tx_stream->CR |= DMA_SxCR_EN; // enable stream
while ((dma->LISR & DMA_LISR_TCIF0) == 0) ; // wait for Rx DMA transfer complete
rx_stream->CR = 0;
tx_stream->CR = 0;
while (rx_stream->CR || tx_stream->CR) ; // wait for stream disable
dma->LIFCR = DMA_LIFCR_CTCIF0 | DMA_LIFCR_CHTIF0 | DMA_LIFCR_CTEIF0;
dma->HIFCR = DMA_HIFCR_CTCIF7 | DMA_HIFCR_CHTIF7 | DMA_HIFCR_CTEIF7;
}
static void
unlock(void)
{
cs_assert();
dmabuf[0] = 6;
transfer(1);
cs_deassert();
}
bool
spiflash_busy(void)
{
cs_assert();
dmabuf[0] = 5;
transfer(2);
cs_deassert();
return dmabuf[1] & 1;
}
static void
wait_ready(void)
{
if (busy)
{
while (spiflash_busy()) ; // wait
busy = false;
}
}
static void
opcode_addr(int addr, int opcode)
{
dmabuf[0] = opcode;
dmabuf[1] = addr >> 16;
dmabuf[2] = addr >> 8;
dmabuf[3] = addr;
}
void
spiflash_read(int addr, void* dst, int len)
{
wait_ready();
cs_assert();
opcode_addr(addr, 0x03);
int header = 4;
while (len > 0)
{
int n = len > (sizeof dmabuf - header) ? (sizeof dmabuf - header) : len;
transfer(header + n);
memcpy(dst, (void*)(dmabuf + header), n);
dst = n + (uint8_t*)dst;
len -= n;
header = 0;
}
cs_deassert();
}
void
spiflash_write_start(int addr, const void* src, int len)
{
addr_delayed = addr;
src_delayed = src;
len_delayed = len;
}
bool
spiflash_writing(void)
{
return len_delayed > 0;
}
bool
spiflash_write_done(void)
{
if (spiflash_writing())
{
int len = 256 - (addr_delayed & 0xFF);
len = (len > len_delayed ? len_delayed : len);
wait_ready();
unlock();
cs_assert();
opcode_addr(addr_delayed, 0x02);
memcpy((void*)(dmabuf + 4), src_delayed, len);
transfer(4 + len);
cs_deassert();
busy = true;
addr_delayed += len;
src_delayed += len;
len_delayed -= len;
return !spiflash_writing();
}
else
{
return true;
}
}
void
spiflash_write(int addr, const void* src, int len)
{
while (!spiflash_write_done());
spiflash_write_start(addr, src, len);
while (!spiflash_write_done());
}
void
spiflash_erase4k(int addr)
{
wait_ready();
unlock();
cs_assert();
opcode_addr(addr, 0x20);
transfer(4);
cs_deassert();
busy = true;
}
void
spiflash_erase64k(int addr)
{
wait_ready();
unlock();
cs_assert();
opcode_addr(addr, 0xD8);
transfer(4);
cs_deassert();
busy = true;
}
void
spiflash_unprotect64k(int addr)
{
wait_ready();
unlock();
cs_assert();
opcode_addr(addr, 0x39);
transfer(4);
cs_deassert();
}
ส็็็็็็็็็็็็็็็็็็็็็็็็็༼ ຈل͜ຈ༽ส้้้้้้้้้้้้้้้้้้้้้้้