📄 spirom.c
字号:
/*
* Copyright (C) 2001, Spectrum Digital, Inc. All Rights Reserved.
*/
#include "5509.h"
#include "util.h"
#define SPIROM_SIZE 0x2000 // in bytes
#define SPIROM_PAGESIZE 64
#define SPIROM_PAGES (SPIROM_SIZE / SPIROM_PAGESIZE)
#define SPIROM_CE GPIO_4
#define SPIROM_OP_WREN 0x06
#define SPIROM_OP_WRDI 0x04
#define SPIROM_OP_RDSR 0x05
#define SPIROM_OP_WRSR 0x01
#define SPIROM_OP_READ 0x03
#define SPIROM_OP_WRITE 0x02
#define SPIROM_STAT_BUSY 0x01
// AIC23 Control Register addresses
#define AIC23_LT_LINE_CTL 0x00 // 0
#define AIC23_RT_LINE_CTL 0x02 // 1
#define AIC23_LT_HP_CTL 0x04 // 2
#define AIC23_RT_HP_CTL 0x06 // 3
#define AIC23_ANALOG_AUDIO_CTL 0x08 // 4
#define AIC23_DIGITAL_AUDIO_CTL 0x0A // 5
#define AIC23_POWER_DOWN_CTL 0x0C // 6
#define AIC23_DIGITAL_IF_FORMAT 0x0E // 7
#define AIC23_SAMPLE_RATE_CTL 0x10 // 8
#define AIC23_DIG_IF_ACTIVATE 0x12 // 9
#define AIC23_RESET_REG 0x1E // F - Writing 0 to this reg triggers reset
unsigned char spirom_buf[SPIROM_PAGESIZE];
unsigned short spirom_cmd[3];
void SPIROM_AssertCE()
{
PC55XX_GPIO pGPIO = (PC55XX_GPIO)C55XX_GPIO_ADDR;
// Configure CE for output, set low
SetMask(pGPIO -> iodir, SPIROM_CE);
ClearMask(pGPIO -> iodata, SPIROM_CE);
}
void SPIROM_DeassertCE()
{
PC55XX_MCSP pMCBSP0 = (PC55XX_MCSP)C55XX_MSP0_ADDR;
PC55XX_GPIO pGPIO = (PC55XX_GPIO)C55XX_GPIO_ADDR;
// Wait for transmission to finish
while (!ReadMask(pMCBSP0 -> spcr2, SPCR2_XRDY));
SWDelayUsec(2);
// Configure CE for output, set high
SetMask(pGPIO -> iodir, SPIROM_CE);
SetMask(pGPIO -> iodata, SPIROM_CE);
}
void SPIROM_Cmd(unsigned short cmd, unsigned short addr, int len)
{
PC55XX_MCSP pMCBSP0 = (PC55XX_MCSP)C55XX_MSP0_ADDR;
unsigned long i, dummy;
// Set up command
spirom_cmd[0] = cmd;
spirom_cmd[1] = (addr >> 8) & 0xff;
spirom_cmd[2] = addr & 0xff;
// Send the command
for (i = 0; i < len; i++)
{
// Wait for transmitter to become free
while (!ReadMask(pMCBSP0 -> spcr2, SPCR2_XRDY));
// Transmit data
pMCBSP0 -> dxr1 = spirom_cmd[i];
// Read response
dummy = pMCBSP0 -> ddr1;
}
}
void SPIROM_SendData(unsigned char *buf, unsigned long len)
{
PC55XX_MCSP pMCBSP0 = (PC55XX_MCSP)C55XX_MSP0_ADDR;
unsigned long i;
unsigned short dummy;
for (i = 0; i < len; i++)
{
// Wait for transmitter to become free
while (!ReadMask(pMCBSP0 -> spcr2, SPCR2_XRDY));
// Transmit data
pMCBSP0 -> dxr1 = spirom_buf[i];
// Read response
dummy = pMCBSP0 -> ddr1;
}
}
void SPIROM_GetData(unsigned char *buf, unsigned short len)
{
PC55XX_MCSP pMCBSP0 = (PC55XX_MCSP)C55XX_MSP0_ADDR;
unsigned char bytedata;
unsigned long i, transferlength;
transferlength = len + 2;
for (i = 0; i < transferlength; i++)
{
// Wait for transmitter to become free
while (!ReadMask(pMCBSP0 -> spcr2, SPCR2_XRDY));
// Transmit dummy value to generate sclk
pMCBSP0 -> dxr1 = 0;
// Read response
bytedata = pMCBSP0 -> ddr1;
if (i > 1)
buf[i - 2] = bytedata;
}
}
unsigned short SPIROM_ReadStatus()
{
unsigned char status, testbuf[16];
SPIROM_AssertCE();
SPIROM_Cmd(SPIROM_OP_RDSR, 0, 1);
SPIROM_GetData(&status, 1);
SPIROM_DeassertCE();
return status;
}
void SPIROM_WaitUntilDone()
{
unsigned short status;
while(1)
{
status = SPIROM_ReadStatus();
if (!(status & SPIROM_STAT_BUSY))
break;
}
// SWDelayMsec(10);
}
unsigned short SPIROM_Read(unsigned long addr, unsigned char *buf, unsigned short len)
{
// Read data
SPIROM_AssertCE();
SPIROM_Cmd(SPIROM_OP_READ, addr, 3);
SPIROM_GetData(buf, len);
SPIROM_DeassertCE();
return 0;
}
unsigned short SPIROM_Write(unsigned long addr, unsigned char *buf, unsigned short len)
{
//Enable writes
SPIROM_AssertCE();
SPIROM_Cmd(SPIROM_OP_WREN, 0x0000, 1);
SPIROM_DeassertCE();
// Write data
SPIROM_AssertCE();
SPIROM_Cmd(SPIROM_OP_WRITE, addr, 3);
SPIROM_SendData(buf, len);
SPIROM_DeassertCE();
SPIROM_WaitUntilDone();
return 0;
}
void SPIROM_Init()
{
PC55XX_MCSP pMCBSP0 = (PC55XX_MCSP)C55XX_MSP0_ADDR;
PC55XX_EXTBUS pExtBus = (PC55XX_EXTBUS)C55XX_EXTBUS_ADDR;
// Configure serial port 0 for McBSP mode
// WriteField(pExtBus -> exbussel, EXBUSSEL_SPMODE_MCBSP, EXBUSSEL_SP0MODE);
// Put the MCBSP in reset
ClearMask(pMCBSP0 -> spcr1, SPCR1_RRST | CLKSTP_NODELAY);
ClearMask(pMCBSP0 -> spcr2, SPCR2_XRST);
// Enable clock stop mode
WriteMask(pMCBSP0 -> spcr1, CLKSTP_NODELAY, SPCR1_CLKSTP);
// Config TX frame parameters (8 bit, single phase, delay 0, 1 word/frame)
Write(pMCBSP0 -> xcr1, XWDLEN1_8 | XFRLEN1_1);
Write(pMCBSP0 -> xcr2, XPHASE_SINGLE | XDATDLY_0);
// Config RX frame parameters (8 bit, single phase, delay 0, 1 word/frame)
Write(pMCBSP0 -> rcr1, RWDLEN1_8 | RFRLEN1_1);
Write(pMCBSP0 -> rcr2, RPHASE_SINGLE | RDATDLY_0);
// Config rate generator for 2MHz divided from CPU clock
WriteField(pMCBSP0 -> srgr1, (dspclk.freq >> 1) - 1, SRGR1_CLKGDV);
WriteField(pMCBSP0 -> srgr1, 10, SRGR1_FWID);
Write(pMCBSP0 -> srgr2, SRGR2_CLKSM);
// Config pins (Master, CLKX output, TX rising CLK, RX rising CLK)
Write(pMCBSP0 -> pcr, PCR_FSXM | PCR_CLKXM | PCR_CLKXP);
// Bring transmitter and receiver out of reset
SetMask(pMCBSP0 -> spcr1, SPCR1_RRST);
SetMask(pMCBSP0 -> spcr2, SPCR2_GRST | SPCR2_XRST);
}
unsigned short SPIROM_Test()
{
unsigned short status;
unsigned long addr;
int i, j;
// Initialize SPI Rom
SPIROM_Init();
// Read status
status = SPIROM_ReadStatus();
// Write pattern to all pages
addr = 0;
for (i = 0; i < SPIROM_PAGES; i++)
{
for (j = 0; j < SPIROM_PAGESIZE; j++)
spirom_buf[j] = (i + j) & 0xff;
SPIROM_Write(addr, spirom_buf, SPIROM_PAGESIZE);
addr += SPIROM_PAGESIZE;
}
// Verify all pages
addr = 0;
for (i = 0; i < SPIROM_PAGES; i++)
{
SPIROM_Read(addr, spirom_buf, SPIROM_PAGESIZE);
for (j = 0; j < SPIROM_PAGESIZE; j++)
if (spirom_buf[j] != ((i + j) & 0xff))
return ERR_SPIROM_VERIFY;
addr += SPIROM_PAGESIZE;
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -