/** * @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 . */ #include #include #include #define READ 0x03 #define WRITE 0x02 #define WREN 0x06 #define WRDS 0x04 #define NSS GPIO_PORT(B, 12) #define SCK GPIO_PORT(B, 13) #define MISO GPIO_PORT(B, 14) #define MOSI GPIO_PORT(B, 15) void flash_xchg(char *byte, int count); void flash_init(void) { gpio_mode(NSS, ALTERNATE); gpio_mode(SCK, ALTERNATE); gpio_mode(MISO, ALTERNATE); gpio_mode(MOSI, ALTERNATE); GPIOB->AFR[1] |= 0x55550000; // alt mode SPI2 // clock enable RCC->APB1ENR1 |= RCC_APB1ENR1_SPI2EN; SPI2->CR1 &= ~(SPI_CR1_BR_Msk); SPI2->CR1 |= (3 << SPI_CR1_BR_Pos); SPI2->CR1 |= SPI_CR1_SSM | SPI_CR1_SSI; SPI2->CR1 |= SPI_CR1_MSTR; SPI2->CR2 &= ~(SPI_CR2_DS_Msk); SPI2->CR2 |= (7 << SPI_CR2_DS_Pos); SPI2->CR2 |= SPI_CR2_SSOE; SPI2->CR2 |= SPI_CR2_FRXTH; SPI2->CR1 |= SPI_CR1_SPE; char buf[4]; buf[0] = READ; buf[1] = 0; buf[2] = 0; buf[3] = 0; flash_xchg(buf, 4); } void flash_xchg(char *byte, int count) { uint32_t status = 0, dummy; SPI2->CR1 &= ~(SPI_CR1_SSI); while (SPI2->SR & SPI_SR_BSY); 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); while (1) { SPI2->DR = 0; do status = SPI2->SR; while (status & SPI_SR_BSY); // discard rx while (status & SPI_SR_RXNE) { dummy = SPI2->DR; status = SPI2->SR; } } SPI2->CR1 |= SPI_CR1_SSI; (void)dummy; } void flash_read(char *buf, uint32_t addr, unsigned int count) { (void)buf; (void)addr; (void)count; if (buf == 0) return; } void flash_write(const char *buf, uint32_t addr, unsigned int count) { (void)buf; (void)addr; (void)count; if (buf == 0) return; }