flash work

master
Clyne Sullivan 7 years ago
parent 275677dd44
commit d9e8fff0bc

Binary file not shown.

@ -1,23 +1,3 @@
/**
* @file flash.c
* Provides functionality for using an external SPI flash
*
* Copyright (C) 2018 Clyne Sullivan
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <stm32l476xx.h> #include <stm32l476xx.h>
#include <gpio.h> #include <gpio.h>
#include <clock.h> #include <clock.h>
@ -27,89 +7,111 @@
#define WREN 0x06 #define WREN 0x06
#define WRDS 0x04 #define WRDS 0x04
#define NSS GPIO_PORT(B, 12) #define SCK GPIO_PORT(C, 14)
#define SCK GPIO_PORT(B, 13) #define SI GPIO_PORT(C, 3)
#define MISO GPIO_PORT(B, 14) #define SO GPIO_PORT(C, 2)
#define MOSI GPIO_PORT(B, 15) #define CS GPIO_PORT(C, 15)
void flash_xchg(char *byte, int count); void flash_out(uint8_t);
uint8_t flash_in(void);
void flash_init(void) void flash_init(void)
{ {
gpio_mode(NSS, ALTERNATE); gpio_mode(SCK, OUTPUT);
gpio_mode(SCK, ALTERNATE); gpio_mode(SI, OUTPUT);
gpio_mode(MISO, ALTERNATE); gpio_mode(CS, OUTPUT);
gpio_mode(MOSI, ALTERNATE); gpio_mode(SO, OUTPUT);
GPIOB->AFR[1] |= 0x55550000; // alt mode SPI2 gpio_dout(SO, 0);
gpio_mode(SO, INPUT);
gpio_dout(CS, 1);
gpio_dout(SCK, 0);
gpio_dout(SI, 0);
//RCC->AHB3ENR |= RCC_AHB3ENR_QSPIEN;
//// 10MHz operation, per datasheet
//QUADSPI->CR &= ~(0xFF << QUADSPI_CR_PRESCALER_Pos);
//QUADSPI->CR |= 7 << QUADSPI_CR_PRESCALER_Pos;
//// pick FSEL! 0=1, 1=2
// clock enable //// FSIZE = 16, 2^17 bits = 1Mb
RCC->APB1ENR1 |= RCC_APB1ENR1_SPI2EN; //QUADSPI->DCR = (16 << QUADSPI_DCR_FSIZE_Pos);
SPI2->CR1 &= ~(SPI_CR1_BR_Msk); //// Memmap mode, single-spi
SPI2->CR1 |= (3 << SPI_CR1_BR_Pos); //QUADSPI->CCR = (3 << QUADSPI_CCR_FMODE_Pos) | (1 << QUADSPI_CCR_DMODE_Pos)
SPI2->CR1 |= SPI_CR1_SSM | SPI_CR1_SSI; // | (2 << QUADSPI_CCR_ADSIZE_Pos) | (1 << QUADSPI_CCR_ADMODE_Pos)
SPI2->CR1 |= SPI_CR1_MSTR; // | (1 << QUADSPI_CCR_IMODE_Pos);
SPI2->CR2 &= ~(SPI_CR2_DS_Msk); //// TODO CCR also takes instruction byte
SPI2->CR2 |= (7 << SPI_CR2_DS_Pos); //QUADSPI->CCR |= (READ << QUADSPI_CCR_INSTRUCTION_Pos);
SPI2->CR2 |= SPI_CR2_SSOE;
SPI2->CR2 |= SPI_CR2_FRXTH;
SPI2->CR1 |= SPI_CR1_SPE;
char buf[4]; //QUADSPI->CR |= QUADSPI_CR_EN;
buf[0] = READ;
buf[1] = 0;
buf[2] = 0;
buf[3] = 0;
flash_xchg(buf, 4);
} }
void flash_xchg(char *byte, int count) void flash_out(uint8_t byte)
{ {
uint32_t status = 0, dummy; for (uint8_t i = 0; i < 8; i++) {
SPI2->CR1 &= ~(SPI_CR1_SSI); gpio_dout(SI, (byte & (1 << (7 - i))));
while (SPI2->SR & SPI_SR_BSY); gpio_dout(SCK, 1);
for (int i = 0; i < count; i++) { delay(1);
SPI2->DR = byte[i]; gpio_dout(SCK, 0);
do status = SPI2->SR;
while (status & SPI_SR_BSY);
// discard rx
while (status & SPI_SR_RXNE) {
dummy = SPI2->DR;
status = SPI2->SR;
} }
} }
do status = SPI2->SR;
while (status & SPI_SR_BSY);
while (1) { void flash_addr(uint32_t addr)
SPI2->DR = 0; {
do status = SPI2->SR; for (uint8_t i = 0; i < 24; i++) {
while (status & SPI_SR_BSY); gpio_dout(SI, (addr & (1 << (23 - i))));
// discard rx gpio_dout(SCK, 1);
while (status & SPI_SR_RXNE) { delay(1);
dummy = SPI2->DR; gpio_dout(SCK, 0);
status = SPI2->SR;
} }
} }
SPI2->CR1 |= SPI_CR1_SSI; uint8_t flash_in(void)
(void)dummy; {
uint8_t byte = 0;
for (uint8_t i = 0; i < 8; i++) {
gpio_dout(SCK, 1);
delay(1);
gpio_dout(SCK, 0);
if (gpio_din(SO))
byte |= (1 << (7 - i));
}
return byte;
} }
void flash_read(char *buf, uint32_t addr, unsigned int count) void flash_read(char *buf, uint32_t addr, unsigned int count)
{ {
(void)buf;
(void)addr;
(void)count;
if (buf == 0) if (buf == 0)
return; return;
gpio_dout(CS, 0);
delay(1);
flash_out(READ);
flash_addr(addr);
for (unsigned int i = 0; i < count; i++)
buf[i] = flash_in();
gpio_dout(CS, 1);
delay(1);
} }
void flash_write(const char *buf, uint32_t addr, unsigned int count) void flash_write(const char *buf, uint32_t addr, unsigned int count)
{ {
(void)buf;
(void)addr;
(void)count;
if (buf == 0) if (buf == 0)
return; return;
gpio_dout(CS, 0);
delay(1);
flash_out(WREN);
gpio_dout(CS, 1);
delay(100);
gpio_dout(CS, 0);
flash_out(WRITE);
flash_addr(addr);
for (unsigned int i = 0; i < count; i++)
flash_out(buf[i]);
gpio_dout(CS, 1);
delay(100);
//gpio_dout(CS, 0);
//flash_out(WRDS);
//gpio_dout(CS, 1);
} }

@ -1,3 +1,23 @@
/**
* @file flash.c
* Provides functionality for using an external SPI flash
*
* Copyright (C) 2018 Clyne Sullivan
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <stm32l476xx.h> #include <stm32l476xx.h>
#include <gpio.h> #include <gpio.h>
#include <clock.h> #include <clock.h>
@ -7,104 +27,89 @@
#define WREN 0x06 #define WREN 0x06
#define WRDS 0x04 #define WRDS 0x04
#define SCK GPIO_PORT(C, 9) #define NSS GPIO_PORT(B, 12)
#define SI GPIO_PORT(B, 8) #define SCK GPIO_PORT(B, 13)
#define SO GPIO_PORT(B, 9) #define MISO GPIO_PORT(B, 14)
#define CS GPIO_PORT(C, 4) #define MOSI GPIO_PORT(B, 15)
void flash_out(uint8_t); void flash_xchg(char *byte, int count);
uint8_t flash_in(void);
void flash_init(void) void flash_init(void)
{ {
gpio_mode(SCK, OUTPUT); gpio_mode(NSS, ALTERNATE);
gpio_mode(SI, OUTPUT); gpio_mode(SCK, ALTERNATE);
gpio_mode(CS, OUTPUT); gpio_mode(MISO, ALTERNATE);
gpio_mode(SO, OUTPUT); gpio_mode(MOSI, ALTERNATE);
gpio_dout(SO, 0); GPIOB->AFR[1] |= 0x55550000; // alt mode SPI2
gpio_mode(SO, INPUT);
gpio_dout(CS, 1);
gpio_dout(SCK, 0);
gpio_dout(SI, 0);
//RCC->AHB3ENR |= RCC_AHB3ENR_QSPIEN;
//// 10MHz operation, per datasheet
//QUADSPI->CR &= ~(0xFF << QUADSPI_CR_PRESCALER_Pos);
//QUADSPI->CR |= 7 << QUADSPI_CR_PRESCALER_Pos;
//// pick FSEL! 0=1, 1=2
//// FSIZE = 16, 2^17 bits = 1Mb // clock enable
//QUADSPI->DCR = (16 << QUADSPI_DCR_FSIZE_Pos); RCC->APB1ENR1 |= RCC_APB1ENR1_SPI2EN;
//// Memmap mode, single-spi SPI2->CR1 &= ~(SPI_CR1_BR_Msk);
//QUADSPI->CCR = (3 << QUADSPI_CCR_FMODE_Pos) | (1 << QUADSPI_CCR_DMODE_Pos) SPI2->CR1 |= (3 << SPI_CR1_BR_Pos);
// | (2 << QUADSPI_CCR_ADSIZE_Pos) | (1 << QUADSPI_CCR_ADMODE_Pos) SPI2->CR1 |= SPI_CR1_SSM | SPI_CR1_SSI;
// | (1 << QUADSPI_CCR_IMODE_Pos); SPI2->CR1 |= SPI_CR1_MSTR;
//// TODO CCR also takes instruction byte SPI2->CR2 &= ~(SPI_CR2_DS_Msk);
//QUADSPI->CCR |= (READ << QUADSPI_CCR_INSTRUCTION_Pos); SPI2->CR2 |= (7 << SPI_CR2_DS_Pos);
SPI2->CR2 |= SPI_CR2_SSOE;
SPI2->CR2 |= SPI_CR2_FRXTH;
SPI2->CR1 |= SPI_CR1_SPE;
//QUADSPI->CR |= QUADSPI_CR_EN; char buf[4];
buf[0] = READ;
buf[1] = 0;
buf[2] = 0;
buf[3] = 0;
flash_xchg(buf, 4);
} }
void flash_out(uint8_t byte) void flash_xchg(char *byte, int count)
{ {
for (uint8_t i = 0; i < 8; i++) { uint32_t status = 0, dummy;
gpio_dout(SI, (byte & (1 << (7 - i)))); SPI2->CR1 &= ~(SPI_CR1_SSI);
gpio_dout(SCK, 1); while (SPI2->SR & SPI_SR_BSY);
gpio_dout(SCK, 0); for (int i = 0; i < count; i++) {
SPI2->DR = byte[i];
do status = SPI2->SR;
while (status & SPI_SR_BSY);
// discard rx
while (status & SPI_SR_RXNE) {
dummy = SPI2->DR;
status = SPI2->SR;
} }
} }
do status = SPI2->SR;
while (status & SPI_SR_BSY);
void flash_addr(uint32_t addr) while (1) {
{ SPI2->DR = 0;
for (uint8_t i = 0; i < 24; i++) { do status = SPI2->SR;
gpio_dout(SI, (addr & (1 << (23 - i)))); while (status & SPI_SR_BSY);
gpio_dout(SCK, 1); // discard rx
gpio_dout(SCK, 0); while (status & SPI_SR_RXNE) {
dummy = SPI2->DR;
status = SPI2->SR;
} }
} }
uint8_t flash_in(void) SPI2->CR1 |= SPI_CR1_SSI;
{ (void)dummy;
uint8_t byte = 0;
for (uint8_t i = 0; i < 8; i++) {
gpio_dout(SCK, 1);
gpio_dout(SCK, 0);
if (gpio_din(SO))
byte |= (1 << (7 - i));
}
return byte;
} }
void flash_read(char *buf, uint32_t addr, unsigned int count) void flash_read(char *buf, uint32_t addr, unsigned int count)
{ {
(void)buf;
(void)addr;
(void)count;
if (buf == 0) if (buf == 0)
return; return;
gpio_dout(CS, 0);
flash_out(READ);
flash_addr(addr);
for (unsigned int i = 0; i < count; i++)
buf[i] = flash_in();
gpio_dout(CS, 1);
} }
void flash_write(const char *buf, uint32_t addr, unsigned int count) void flash_write(const char *buf, uint32_t addr, unsigned int count)
{ {
(void)buf;
(void)addr;
(void)count;
if (buf == 0) if (buf == 0)
return; return;
gpio_dout(CS, 0);
flash_out(WREN);
gpio_dout(CS, 1);
gpio_dout(CS, 0);
flash_out(WRITE);
flash_addr(addr);
for (unsigned int i = 0; i < count; i++)
flash_out(buf[i]);
gpio_dout(CS, 1);
delay(100);
//gpio_dout(CS, 0);
//flash_out(WRDS);
//gpio_dout(CS, 1);
} }

@ -57,6 +57,7 @@ int main(void)
serial_init(); serial_init();
random_init(); random_init();
keypad_init(); keypad_init();
flash_init();
gpio_mode(GPIOA, 5, OUTPUT); gpio_mode(GPIOA, 5, OUTPUT);
@ -74,8 +75,16 @@ void kmain(void)
dsp_init(); dsp_init();
dsp_rect(0, 0, LCD_WIDTH, LCD_HEIGHT, dsp_color(0, 0, 0)); dsp_rect(0, 0, LCD_WIDTH, LCD_HEIGHT, dsp_color(0, 0, 0));
dsp_cursoron(); dsp_cursoron();
keypad_start();
task_start(task_interpreter, 4096); char buf[2] = {0, 0};
buf[0] = 'A';
flash_write(buf, 42, 1);
buf[0] = 0;
flash_read(buf, 42, 1);
dsp_puts(buf);
//keypad_start();
//task_start(task_interpreter, 4096);
while (1) { while (1) {
gpio_dout(GPIOA, 5, 1); gpio_dout(GPIOA, 5, 1);

Loading…
Cancel
Save