rtl8710-openocd/spi_flash.c
2016-08-22 11:22:31 +03:00

128 lines
4 KiB
C

#include "spi_flash.h"
#include "rtl8710.h"
#include "mask.h"
static void spi_flash_send(uint8_t byte){
// while(!(SPI_FLASH->SR & SPI_SR_TFNF));
SPI_FLASH->DR = byte;
}
static uint8_t spi_flash_recv(){
while(!(SPI_FLASH->RXFLR & 0x0FFF));
return(SPI_FLASH->DR);
}
void spi_flash_init(){
PERI_ON->PESOC_CLK_CTRL |= PERI_ON_CLK_CTRL_ACTCK_FLASH_EN | PERI_ON_CLK_CTRL_SLPCK_FLASH_EN; // enable spi flash peripheral clock
PERI_ON->SOC_FUNC_EN |= PERI_ON_SOC_FUNC_EN_FLASH; // enable spi flash peripheral
mask32_set(PERI_ON->CPU_PERIPHERAL_CTRL, PERI_ON_CPU_PERIPHERAL_CTRL_SPI_FLASH_PIN_SEL, 0); // select spi flash pinout (0 - internal)
PERI_ON->CPU_PERIPHERAL_CTRL |= PERI_ON_CPU_PERIPHERAL_CTRL_SPI_FLASH_PIN_EN; // enable spi flash pins
SPI_FLASH->SSIENR = 0; // disable SPI FLASH operation
SPI_FLASH->IMR = 0; // disable all interrupts
SPI_FLASH->SER = SPI_SER_SS0; // use first "slave select" pin
SPI_FLASH->BAUDR = 2; // baud rate, default value
SPI_FLASH->TXFTLR = 0; // tx fifo threshold
SPI_FLASH->RXFTLR = 0; // rx fifo threshold
SPI_FLASH->DMACR = 0; // disable DMA
}
uint16_t spi_flash_read(uint32_t address, void *buf, uint16_t count){
uint16_t i;
if(!count)return(0);
if(count > 16)count = 16;
SPI_FLASH->CTRLR0 = mask32(SPI_CTRLR0_TMOD, 3) | mask32(SPI_CTRLR0_CMD_CH, 0) | mask32(SPI_CTRLR0_ADDR_CH, 0) | mask32(SPI_CTRLR0_DATA_CH, 0);
SPI_FLASH->CTRLR1 = count;
spi_flash_send(0x03); // flash command "read"
spi_flash_send((address >> 16) & 0xFF); // address * 3
spi_flash_send((address >> 8) & 0xFF);
spi_flash_send((address >> 0) & 0xFF);
SPI_FLASH->SSIENR = 1;
for(i = 0; i < count; i++){
((uint8_t *)buf)[i] = spi_flash_recv();
}
while(SPI_FLASH->SR & SPI_SR_SSI);
SPI_FLASH->SSIENR = 0;
return(count);
}
uint32_t spi_flash_jedec_id(){
uint32_t id;
SPI_FLASH->CTRLR0 = mask32(SPI_CTRLR0_TMOD, 3) | mask32(SPI_CTRLR0_CMD_CH, 0) | mask32(SPI_CTRLR0_ADDR_CH, 0) | mask32(SPI_CTRLR0_DATA_CH, 0);
SPI_FLASH->CTRLR1 = 3;
SPI_FLASH->SSIENR = 1;
spi_flash_send(0x9F); // jedec id
id = spi_flash_recv();
id |= ((uint32_t)spi_flash_recv() << 8);
id |= ((uint32_t)spi_flash_recv() << 16);
while(SPI_FLASH->SR & SPI_SR_SSI);
SPI_FLASH->SSIENR = 0;
return(id);
}
uint8_t spi_flash_status(){
uint8_t status;
SPI_FLASH->CTRLR0 = mask32(SPI_CTRLR0_TMOD, 3) | mask32(SPI_CTRLR0_CMD_CH, 0) | mask32(SPI_CTRLR0_ADDR_CH, 0) | mask32(SPI_CTRLR0_DATA_CH, 0);
SPI_FLASH->CTRLR1 = 1;
SPI_FLASH->SSIENR = 1;
spi_flash_send(0x05); // read status
status = spi_flash_recv();
while(SPI_FLASH->SR & SPI_SR_SSI);
SPI_FLASH->SSIENR = 0;
return(status);
}
void spi_flash_cmd(uint8_t cmd){
SPI_FLASH->CTRLR0 = mask32(SPI_CTRLR0_TMOD, 1) | mask32(SPI_CTRLR0_CMD_CH, 0) | mask32(SPI_CTRLR0_ADDR_CH, 0) | mask32(SPI_CTRLR0_DATA_CH, 0);
SPI_FLASH->SSIENR = 1;
spi_flash_send(cmd);
while(SPI_FLASH->SR & SPI_SR_SSI);
SPI_FLASH->SSIENR = 0;
}
void spi_flash_sector_erase(uint32_t address){
SPI_FLASH->CTRLR0 = mask32(SPI_CTRLR0_TMOD, 1) | mask32(SPI_CTRLR0_CMD_CH, 0) | mask32(SPI_CTRLR0_ADDR_CH, 0) | mask32(SPI_CTRLR0_DATA_CH, 0);
SPI_FLASH->SSIENR = 1;
spi_flash_send(0x20); // sector erase
spi_flash_send((address >> 16) & 0xFF);
spi_flash_send((address >> 8) & 0xFF);
spi_flash_send((address >> 0) & 0xFF);
while(SPI_FLASH->SR & SPI_SR_SSI);
SPI_FLASH->SSIENR = 0;
}
uint16_t spi_flash_write(uint32_t address, const void *buf, uint16_t count){
uint16_t i;
if(!count)return(0);
if(count > 256)count = 256;
SPI_FLASH->CTRLR0 = mask32(SPI_CTRLR0_TMOD, 1) | mask32(SPI_CTRLR0_CMD_CH, 0) | mask32(SPI_CTRLR0_ADDR_CH, 0) | mask32(SPI_CTRLR0_DATA_CH, 0);
SPI_FLASH->SSIENR = 1;
spi_flash_send(0x02); // write
spi_flash_send((address >> 16) & 0xFF);
spi_flash_send((address >> 8) & 0xFF);
spi_flash_send((address >> 0) & 0xFF);
for(i = 0; i < count; i++){
spi_flash_send(((uint8_t *)buf)[i]);
}
while(!(SPI_FLASH->SR & SPI_SR_TFE));
while(SPI_FLASH->SR & SPI_SR_SSI);
SPI_FLASH->SSIENR = 0;
return(count);
}
void spi_flash_wait_busy(){
while(spi_flash_status() & 0x01);
}
void spi_flash_wait_wel(){
while(!(spi_flash_status() & 0x02));
}