/**************************************************************************//**
* [url=home.php?mod=space&uid=288409]@file[/url] main.c
* [url=home.php?mod=space&uid=895143]@version[/url] V2.0
* $Revision: 11 $
* $Date: 15/03/04 9:47a $
* [url=home.php?mod=space&uid=247401]@brief[/url] Access the SPI Flash through a SPI interface.
*
* @note
* Copyright (C) 2015 Nuvoton Technology Corp. All rights reserved.
*
******************************************************************************/
#include <stdio.h>
#include "NUC505Series.h"
#define TEST_NUMBER 1 /* page numbers */
#define TEST_LENGTH 256 /* length */
#define SPI_FLASH_PORT SPI0
uint8_t SrcArray[TEST_LENGTH];
uint8_t DestArray[TEST_LENGTH];
/* Function prototype declaration */
void SYS_Init(void);
void UART0_Init(void);
void SPI0_Init(void);
uint16_t SpiFlash_ReadMidDid(void)
{
uint8_t u8RxData[6], u8IDCnt = 0;
// /CS: active
SPI_SET_SS_LOW(SPI_FLASH_PORT);
// send Command: 0x90, Read Manufacturer/Device ID
SPI_WRITE_TX(SPI_FLASH_PORT, 0x90);
// send 24-bit '0', dummy
SPI_WRITE_TX(SPI_FLASH_PORT, 0x00);
SPI_WRITE_TX(SPI_FLASH_PORT, 0x00);
SPI_WRITE_TX(SPI_FLASH_PORT, 0x00);
// receive 16-bit
SPI_WRITE_TX(SPI_FLASH_PORT, 0x00);
SPI_WRITE_TX(SPI_FLASH_PORT, 0x00);
// wait tx finish
while(SPI_IS_BUSY(SPI_FLASH_PORT));
// /CS: de-active
SPI_SET_SS_HIGH(SPI_FLASH_PORT);
while(!SPI_GET_RX_FIFO_EMPTY_FLAG(SPI_FLASH_PORT))
u8RxData[u8IDCnt ++] = SPI_READ_RX(SPI_FLASH_PORT);
return ( (u8RxData[4]<<8) | u8RxData[5] );
}
void SpiFlash_ChipErase(void)
{
// /CS: active
SPI_SET_SS_LOW(SPI_FLASH_PORT);
// send Command: 0x06, Write enable
SPI_WRITE_TX(SPI_FLASH_PORT, 0x06);
// wait tx finish
while(SPI_IS_BUSY(SPI_FLASH_PORT));
// /CS: de-active
SPI_SET_SS_HIGH(SPI_FLASH_PORT);
//////////////////////////////////////////
// /CS: active
SPI_SET_SS_LOW(SPI_FLASH_PORT);
// send Command: 0xC7, Chip Erase
SPI_WRITE_TX(SPI_FLASH_PORT, 0xC7);
// wait tx finish
while(SPI_IS_BUSY(SPI_FLASH_PORT));
// /CS: de-active
SPI_SET_SS_HIGH(SPI_FLASH_PORT);
SPI_ClearRxFIFO(SPI0);
}
uint8_t SpiFlash_ReadStatusReg(void)
{
// /CS: active
SPI_SET_SS_LOW(SPI_FLASH_PORT);
// send Command: 0x05, Read status register
SPI_WRITE_TX(SPI_FLASH_PORT, 0x05);
// read status
SPI_WRITE_TX(SPI_FLASH_PORT, 0x00);
// wait tx finish
while(SPI_IS_BUSY(SPI_FLASH_PORT));
// /CS: de-active
SPI_SET_SS_HIGH(SPI_FLASH_PORT);
// skip first rx data
SPI_READ_RX(SPI_FLASH_PORT);
return (SPI_READ_RX(SPI_FLASH_PORT) & 0xff);
}
void SpiFlash_WriteStatusReg(uint8_t u8Value)
{
// /CS: active
SPI_SET_SS_LOW(SPI_FLASH_PORT);
// send Command: 0x06, Write enable
SPI_WRITE_TX(SPI_FLASH_PORT, 0x06);
// wait tx finish
while(SPI_IS_BUSY(SPI_FLASH_PORT));
// /CS: de-active
SPI_SET_SS_HIGH(SPI_FLASH_PORT);
///////////////////////////////////////
// /CS: active
SPI_SET_SS_LOW(SPI_FLASH_PORT);
// send Command: 0x01, Write status register
SPI_WRITE_TX(SPI_FLASH_PORT, 0x01);
// write status
SPI_WRITE_TX(SPI_FLASH_PORT, u8Value);
// wait tx finish
while(SPI_IS_BUSY(SPI_FLASH_PORT));
// /CS: de-active
SPI_SET_SS_HIGH(SPI_FLASH_PORT);
}
void SpiFlash_WaitReady(void)
{
uint8_t ReturnValue;
do {
ReturnValue = SpiFlash_ReadStatusReg();
ReturnValue = ReturnValue & 1;
} while(ReturnValue!=0); // check the BUSY bit
}
void SpiFlash_NormalPageProgram(uint32_t StartAddress, uint8_t *u8DataBuffer)
{
uint32_t i = 0;
// /CS: active
SPI_SET_SS_LOW(SPI_FLASH_PORT);
// send Command: 0x06, Write enable
SPI_WRITE_TX(SPI_FLASH_PORT, 0x06);
// wait tx finish
while(SPI_IS_BUSY(SPI_FLASH_PORT));
// /CS: de-active
SPI_SET_SS_HIGH(SPI_FLASH_PORT);
// /CS: active
SPI_SET_SS_LOW(SPI_FLASH_PORT);
// send Command: 0x02, Page program
SPI_WRITE_TX(SPI_FLASH_PORT, 0x02);
// send 24-bit start address
SPI_WRITE_TX(SPI_FLASH_PORT, (StartAddress>>16) & 0xFF);
SPI_WRITE_TX(SPI_FLASH_PORT, (StartAddress>>8) & 0xFF);
SPI_WRITE_TX(SPI_FLASH_PORT, StartAddress & 0xFF);
// write data
while(1) {
if(!SPI_GET_TX_FIFO_FULL_FLAG(SPI_FLASH_PORT)) {
SPI_WRITE_TX(SPI_FLASH_PORT, u8DataBuffer[i++]);
if(i >= 255) break;
}
}
// wait tx finish
while(SPI_IS_BUSY(SPI_FLASH_PORT));
// /CS: de-active
SPI_SET_SS_HIGH(SPI_FLASH_PORT);
SPI_ClearRxFIFO(SPI_FLASH_PORT);
}
void SpiFlash_NormalRead(uint32_t StartAddress, uint8_t *u8DataBuffer)
{
uint32_t i;
// /CS: active
SPI_SET_SS_LOW(SPI_FLASH_PORT);
// send Command: 0x03, Read data
SPI_WRITE_TX(SPI_FLASH_PORT, 0x03);
// send 24-bit start address
SPI_WRITE_TX(SPI_FLASH_PORT, (StartAddress>>16) & 0xFF);
SPI_WRITE_TX(SPI_FLASH_PORT, (StartAddress>>8) & 0xFF);
SPI_WRITE_TX(SPI_FLASH_PORT, StartAddress & 0xFF);
while(SPI_IS_BUSY(SPI_FLASH_PORT));
// clear RX buffer
SPI_ClearRxFIFO(SPI_FLASH_PORT);
// read data
for(i=0; i<256; i++) {
SPI_WRITE_TX(SPI_FLASH_PORT, 0x00);
while(SPI_IS_BUSY(SPI_FLASH_PORT));
u8DataBuffer[i] = SPI_READ_RX(SPI_FLASH_PORT);
}
// wait tx finish
while(SPI_IS_BUSY(SPI_FLASH_PORT));
// /CS: de-active
SPI_SET_SS_HIGH(SPI_FLASH_PORT);
}
/* Main */
int main(void)
{
uint32_t u32ByteCount, u32FlashAddress, u32PageNumber;
uint32_t nError = 0;
uint16_t u16ID;
/* Init System, IP clock and multi-function I/O */
SYS_Init();
/* Init UART0 to 115200-8n1 for print message */
UART0_Init();
/* Init SPI0, IP clock and multi-function I/O */
SPI0_Init();
/* Configure SPI_FLASH_PORT as a master, MSB first, 8-bit transaction, SPI Mode-0 timing, clock is 2MHz */
SPI_Open(SPI_FLASH_PORT, SPI_MASTER, SPI_MODE_0, 8, 2000000);
/* Enable the automatic hardware slave select function. Select the SS0 pin and configure as low-active. */
SPI_EnableAutoSS(SPI_FLASH_PORT, SPI_SS, SPI_SS_ACTIVE_LOW);
SPI_ENABLE(SPI_FLASH_PORT);
printf("\n+------------------------------------------------------------------------+\n");
printf("| NUC505 SPI Sample with SPI Flash |\n");
printf("+------------------------------------------------------------------------+\n");
/* Wait ready */
SpiFlash_WaitReady();
/// if((u16ID = SpiFlash_ReadMidDid()) != 0x1C14) {
if((u16ID = SpiFlash_ReadMidDid()) != 0xEF14) {
printf("Wrong ID, 0x%x\n", u16ID);
return -1;
} else
printf("Flash found: Winbond 25Q16OVSEG ...\n");
printf("Erase chip ...");
/* Erase SPI flash */
SpiFlash_ChipErase();
/* Wait ready */
SpiFlash_WaitReady();
printf("[OK]\n");
/* init source data buffer */
for(u32ByteCount=0; u32ByteCount<TEST_LENGTH; u32ByteCount++) {
SrcArray[u32ByteCount] = u32ByteCount;
}
printf("Start to normal write data to Flash ...");
/* Program SPI flash */
u32FlashAddress = 0;
for(u32PageNumber=0; u32PageNumber<TEST_NUMBER; u32PageNumber++) {
/* page program */
SpiFlash_NormalPageProgram(u32FlashAddress, SrcArray);
SpiFlash_WaitReady();
u32FlashAddress += 0x100;
}
printf("[OK]\n");
/* clear destination data buffer */
for(u32ByteCount=0; u32ByteCount<TEST_LENGTH; u32ByteCount++) {
DestArray[u32ByteCount] = 0;
}
printf("Normal Read & Compare ...");
/* Read SPI flash */
u32FlashAddress = 0;
for(u32PageNumber=0; u32PageNumber<TEST_NUMBER; u32PageNumber++) {
/* page read */
SpiFlash_NormalRead(u32FlashAddress, DestArray);
u32FlashAddress += 0x100;
for(u32ByteCount=0; u32ByteCount<TEST_LENGTH; u32ByteCount++) {
if(DestArray[u32ByteCount] != SrcArray[u32ByteCount])
nError ++;
}
}
if(nError == 0)
printf("[OK]\n");
else
printf("[FAIL]\n");
while(1);
}
void SYS_Init(void)
{
/*---------------------------------------------------------------------------------------------------------*/
/* Init System Clock */
/*---------------------------------------------------------------------------------------------------------*/
/* Unlock protected registers */
//SYS_UnlockReg();
/* Enable XTAL */
CLK->PWRCTL |= CLK_PWRCTL_HXTEN_Msk;
CLK_SetCoreClock(FREQ_96MHZ);
/* PCLK divider */
CLK_SetModuleClock(PCLK_MODULE, NULL, 1);
/* Lock protected registers */
//SYS_LockReg();
}
void UART0_Init(void)
{
/* Enable UART0 Module clock */
CLK_EnableModuleClock(UART0_MODULE);
/* UART0 module clock from EXT */
CLK_SetModuleClock(UART0_MODULE, CLK_UART0_SRC_EXT, 0);
/* Reset IP */
SYS_ResetModule(UART0_RST);
/* Configure UART0 and set UART0 Baud-rate */
UART_Open(UART0, 115200);
/*---------------------------------------------------------------------------------------------------------*/
/* Init I/O Multi-function */
/*---------------------------------------------------------------------------------------------------------*/
/* Configure multi-function pins for UART0 RXD and TXD */
SYS->GPB_MFPL = (SYS->GPB_MFPL & (~SYS_GPB_MFPL_PB0MFP_Msk) ) | SYS_GPB_MFPL_PB0MFP_UART0_TXD;
SYS->GPB_MFPL = (SYS->GPB_MFPL & (~SYS_GPB_MFPL_PB1MFP_Msk) ) | SYS_GPB_MFPL_PB1MFP_UART0_RXD;
}
void SPI0_Init(void)
{
/* Enable SPI0 Module clock */
CLK_EnableModuleClock(SPI0_MODULE);
/* SPI0 module clock from EXT */
CLK_SetModuleClock(SPI0_MODULE, CLK_SPI0_SRC_PLL, 0);
/* Reset IP */
SYS_ResetModule(SPI0_RST);
/*---------------------------------------------------------------------------------------------------------*/
/* Init I/O Multi-function */
/*---------------------------------------------------------------------------------------------------------*/
/* Configure multi-function pins for SPI0 */
SYS->GPB_MFPL = (SYS->GPB_MFPL & (~SYS_GPB_MFPL_PB2MFP_Msk) ) | SYS_GPB_MFPL_PB2MFP_SPI0_SS;
SYS->GPB_MFPL = (SYS->GPB_MFPL & (~SYS_GPB_MFPL_PB3MFP_Msk) ) | SYS_GPB_MFPL_PB3MFP_SPI0_CLK;
SYS->GPB_MFPL = (SYS->GPB_MFPL & (~SYS_GPB_MFPL_PB4MFP_Msk) ) | SYS_GPB_MFPL_PB4MFP_SPI0_MOSI;
SYS->GPB_MFPL = (SYS->GPB_MFPL & (~SYS_GPB_MFPL_PB5MFP_Msk) ) | SYS_GPB_MFPL_PB5MFP_SPI0_MISO;
}
/*** (C) COPYRIGHT 2015 Nuvoton Technology Corp. ***/
这个是吧