Mam problem z podstawowym dogadaniem się z pamięcią szeregową M25P16 po SPI z STM32F103VB. Pamięć ta jest podłączona do pinów SPI1, ale nie tych, które są domyślnie dla niego przeznaczone w porcie A tylko na porcie B. Stąd potrzeba ich remapowania.
Myślę, że w kodzie odpowiedzialnym za obsługę tej pamięci zrobiłem wszystko co potrzeba:
- włączone zegary,
- skonfigurowane odpowiednie piny jako AF,
- włączone AFIO,
- włączone remapowanie SPI1,
- wyłączony JTAG.
Niestety odczyty bajtu statusu czy ciągu ID zawsze zwracają zera. I teraz nie wiem, czy coś jest ze sprzętem, czy w kodzie jest coś nie tak albo jeszcze czegoś zapomniałem dopisać w kwestii remapowania (najbardziej parawdopodobne). Jeśli ktoś jeszcze mógłby rzucić fachowym okiem...
ps1. Nieistotne fragmenty wycięte.
ps2. Sorry za ang. komentarze - ale są krótsze
Kod: Zaznacz cały
/**
******************************************************************************
* @file main.c
* @version V1.0
(...)
*/
// includes
#include "stm32f10x.h"
#include "status_leds.h"
#include "ext_memory.h"
// global variables
uint32_t dupsko;
// start-up function - prepare MCU
int board_startup(void)
{
(...)
leds_init();
ext_mem_init();
return(0);
}
// main function
int main(void)
{
uint8_t memstat;
board_startup(); // start hardware
LEDPWR_ON; // PWR LED on - we are alive
ext_mem_clear_buffer(); // erase memory buffer
ext_mem_get_id(); // read memory id (FUTURE: raise error if missmatch)
memstat = ext_mem_get_status(); // read memory status byte
LEDMODE_1; // indicate mode 1 - no protection valves
for(;;){
(...)
}
}
// end of main
Kod: Zaznacz cały
/*
* ext_memory.h
(...)
*/
#include "stm32f10x.h"
#ifndef EXT_MEMORY_H_
#define EXT_MEMORY_H_
// Define pins and ports
#define SPI_PORT GPIOB // All SPI HW pins at Port B
#define SPI_MISO GPIO_Pin_4 // PB4 - SPI1 MISO Remap
#define SPI_MOSI GPIO_Pin_5 // PB5 - SPI1 MOSI Remap
#define SPI_SCK GPIO_Pin_3 // PB3 - SPI1 SCK Remap
#define SPI_CS GPIO_Pin_15 // PA15 - Regular GPIO
#define SPI_CS_PORT GPIOA
#define SPI_WP GPIO_Pin_6 // PB6 - Regular GPIO Low Level
#define SPI_WP_PORT GPIOB
// Define APB clock bits to enable
#define RCC_SPI RCC_APB2Periph_SPI1
#define RCC_GPIO RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB
// Declare Macros
#define MEM_SELECT GPIO_ResetBits(SPI_CS_PORT, SPI_CS)
#define MEM_DESELECT GPIO_SetBits(SPI_CS_PORT, SPI_CS)
#define MEM_PROTECT GPIO_ResetBits(SPI_WP_PORT, SPI_WP)
#define MEM_UNPROTECT GPIO_SetBits(SPI_WP_PORT, SPI_WP)
// ------------------------------------------------------------------
// Memory sectors
#define SECTOR_SIZE 0x00010000
#define PAGE_SIZE 0x00000100
#define MAX_PAGE (PAGE_SIZE - 1)
(...)
// Memory commands
#define CMD_WRITE_STATUS_REG 0x01
#define CMD_PAGE_PROGRAM 0x02
#define CMD_READ_DATA_BYTES 0x03
#define CMD_WRITE_DISABLE 0x04
#define CMD_READ_STATUS_REG 0x05
#define CMD_WRITE_ENABLE 0x06
#define CMD_READ_DATA_FAST 0x0b
#define CMD_READ_ID1 0x9f
#define CMD_READ_ID2 0x9e
#define CMD_LEAVE_PD 0xab
#define CMD_ENTER_PD 0xb9
#define CMD_BULK_ERASE 0xc7
#define CMD_SECTOR_ERASE 0xd8
// ##################################################################
uint8_t page_buffer[PAGE_SIZE]; // read/write buffer
uint8_t mem_id[20]; // 3 byte ID and max 17 bytes of signature
// Declare input output functions
void ext_mem_init(void);
uint8_t ext_mem_exchange_byte(uint8_t byte);
uint8_t ext_mem_get_status(void);
void ext_mem_get_id(void);
void ext_mem_clear_buffer(void);
(...)
#endif /* EXT_MEMORY_H_ */
Kod: Zaznacz cały
/*
* ext_memory.c
*
(...)
*/
#include "ext_memory.h"
#include "stm32f10x.h"
void ext_mem_init(void)
{
GPIO_InitTypeDef gpio;
SPI_InitTypeDef spi;
// Enable some peripherials
RCC_APB2PeriphClockCmd(RCC_GPIO , ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO , ENABLE);
RCC_APB2PeriphClockCmd(RCC_SPI , ENABLE);
// Remap HW SPI1 to alternative location and disable JTAG
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable , ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SPI1, ENABLE);
// Software part
GPIO_StructInit(&gpio);
gpio.GPIO_Pin = SPI_CS;
gpio.GPIO_Mode = GPIO_Mode_Out_PP;
gpio.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(SPI_CS_PORT, &gpio);
gpio.GPIO_Pin = SPI_WP;
GPIO_Init(SPI_WP_PORT, &gpio);
MEM_DESELECT;
MEM_UNPROTECT;
// Hardware Part - SPI
GPIO_StructInit(&gpio);
gpio.GPIO_Pin = SPI_SCK;
gpio.GPIO_Mode = GPIO_Mode_AF_PP;
gpio.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(SPI_PORT, &gpio);
gpio.GPIO_Pin = SPI_MISO;
gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
gpio.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(SPI_PORT, &gpio);
gpio.GPIO_Pin = SPI_MOSI;
gpio.GPIO_Mode = GPIO_Mode_AF_PP;
gpio.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(SPI_PORT, &gpio);
SPI_StructInit(&spi);
spi.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
spi.SPI_DataSize = SPI_DataSize_8b;
spi.SPI_CPHA = SPI_CPHA_1Edge;
spi.SPI_CPOL = SPI_CPOL_Low;
spi.SPI_FirstBit = SPI_FirstBit_MSB;
spi.SPI_Mode = SPI_Mode_Master;
spi.SPI_NSS = SPI_NSS_Soft;
spi.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32;
SPI_Init(SPI1, &spi);
// Start SPI
SPI_Cmd(SPI1, ENABLE);
}
// SPI communication
uint8_t ext_mem_exchange_byte(uint8_t byte)
{
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI1, byte);
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
return SPI_I2S_ReceiveData(SPI1);
}
// read memory status
uint8_t ext_mem_get_status(void)
{
MEM_SELECT;
ext_mem_exchange_byte(CMD_READ_STATUS_REG);
return(ext_mem_exchange_byte(0xff));
MEM_DESELECT;
}
// read memory status
void ext_mem_get_id(void)
{
uint32_t i;
MEM_SELECT;
ext_mem_exchange_byte(CMD_READ_ID1);
for(i = 0; i < 19; i++)
mem_id[i] = ext_mem_exchange_byte(0xff); // dummy write
MEM_DESELECT;
}
// clear buffer with
void ext_mem_clear_buffer(void)
{
uint32_t i;
for(i = 0; i < MAX_PAGE; i++)
page_buffer[i] = 0xff; // as unprogrammed
}
(...)