📄 ssp.cpp
字号:
}
pInit->data_size--;
// Validate frame "format"
if ((pInit->format != MOTOROLA_SPI) &&
(pInit->format != TI_SSP) &&
(pInit->format != MICROWIRE))
{
nResult = VGXSSP_INVALID_FORMAT;
break;
}
// Validate "phase"
if ((pInit->phase != PH0) &&
(pInit->phase != PH1))
{
nResult = VGXSSP_INVALID_PHASE;
break;
}
// Validate "polarity"
if ((pInit->polarity != RISING_EDGE) &&
(pInit->polarity != FALLING_EDGE))
{
nResult = VGXSSP_INVALID_POLARITY;
break;
}
// Register SSP interrupt routine.
if (!RegisterHandler(
m_SSPInfo[pInit->ssp].IntHandler,
m_SSPInfo[pInit->ssp].dwIntMask))
{
nResult = VGXSSP_INT_FAILED;
break;
}
// Init timeouts
m_SSPInfo[pInit->ssp].read_timeout = pInit->read_timeout;
m_SSPInfo[pInit->ssp].write_timeout = pInit->write_timeout;
// Init the receive buffer.
m_SSPInfo[pInit->ssp].readBuffer.SetBuffer(SSP_READ_BUFFER_SIZE);
// Enable the power gate.
DWORD value = peekRegisterDWord(CURRENT_POWER_GATE);
value = FIELD_SET(value, CURRENT_POWER_GATE, SSP0_SSP1, ENABLE);
setPower(value, peekRegisterDWord(CURRENT_POWER_CLOCK));
switch (pInit->ssp)
{
case SSP0:
{
// Select SSP0 pins.
value = peekRegisterDWord(GPIO_MUX_HIGH);
value = FIELD_SET(value, GPIO_MUX_HIGH, 32, SSP0); // 0: TXD
value = FIELD_SET(value, GPIO_MUX_HIGH, 33, SSP0); // 0: RXD
value = FIELD_SET(value, GPIO_MUX_HIGH, 34, SSP0); // 0: SFRMOUT
value = FIELD_SET(value, GPIO_MUX_HIGH, 35, SSP0); // 0: SFRMIN
value = FIELD_SET(value, GPIO_MUX_HIGH, 36, SSP0); // 0: SCLKOUT
pokeRegisterDWord(GPIO_MUX_HIGH, value);
}
break;
case SSP1:
{
// Select SSP1 instead of UART1.
pokeRegisterDWord(MISC_CTRL,
FIELD_SET(peekRegisterDWord(MISC_CTRL), MISC_CTRL_UART1, SELECT, SSP));
// Select SSP1 pins.
value = peekRegisterDWord(GPIO_MUX_HIGH);
value = FIELD_SET(value, GPIO_MUX_HIGH, 41, UART1_SSP1); // 1: TXD
value = FIELD_SET(value, GPIO_MUX_HIGH, 42, UART1_SSP1); // 1: RXD
value = FIELD_SET(value, GPIO_MUX_HIGH, 43, UART1_SSP1); // 1: SFRMOUT
value = FIELD_SET(value, GPIO_MUX_HIGH, 44, UART1_SSP1); // 1: SFRMIN
value = FIELD_SET(value, GPIO_MUX_HIGH, 45, SSP1); // 1: SCLKIN
pokeRegisterDWord(GPIO_MUX_HIGH, value);
}
break;
};
// Init clock prescale
pokeRegisterDWord(m_SSPInfo[pInit->ssp].dwPrescaleReg,
FIELD_VALUE(0, SSP_0_CLOCK_PRESCALE, DIVISOR, pInit->clock_prescale));
// Init SSP control register 0.
value = 0;
value = FIELD_VALUE(value, SSP_0_CONTROL_0, CLOCK_RATE, pInit->serial_clock_rate);
value = FIELD_VALUE(value, SSP_0_CONTROL_0, FRAME_FORMAT, pInit->format);
value = FIELD_VALUE(value, SSP_0_CONTROL_0, DATA_SIZE, pInit->data_size);
value = FIELD_VALUE(value, SSP_0_CONTROL_0, SCLKOUT_PHASE, pInit->phase);
value = FIELD_VALUE(value, SSP_0_CONTROL_0, SCLKOUT_POLARITY, pInit->polarity);
pokeRegisterDWord(m_SSPInfo[pInit->ssp].dwControl0Reg, value);
// Init SSP control register 1.
value = 0;
value = FIELD_VALUE(value, SSP_0_CONTROL_1, MODE_SELECT, pInit->master? 0 : 1);
value = FIELD_SET (value, SSP_0_CONTROL_1, STATUS, ENABLE);
value = FIELD_VALUE(value, SSP_0_CONTROL_1, LOOP_BACK, pInit->loopback? 1 : 0);
value = FIELD_SET (value, SSP_0_CONTROL_1, OVERRUN_INTERRUPT, ENABLE);
value = FIELD_SET (value, SSP_0_CONTROL_1, TRANSMIT_INTERRUPT, DISABLE);
value = FIELD_SET (value, SSP_0_CONTROL_1, RECEIVE_INTERRUPT, ENABLE);
pokeRegisterDWord(m_SSPInfo[pInit->ssp].dwControl1Reg, value);
// Set the flag
m_SSPInfo[pInit->ssp].Active = TRUE;
}
while (0);
#endif // DISABLE_INTERRUPT_MANAGEMENT
MESSAGE(MESSAGE_ZONE, (TEXT("-SMI::i2cOpen\r\n")));
return nResult;
}
///////////////////////////////////////////////////////////////////////////////
// Closes specified SSP channel.
ULONG SMI::sspClose(VGXSSP_ENUM ssp)
{
MESSAGE(MESSAGE_ZONE, (TEXT("+SMI::sspClose\r\n")));
#ifdef DISABLE_INTERRUPT_MANAGEMENT
ULONG nResult = VGXSSP_NOT_SUPPORTED;
#else
ULONG nResult = VGXSSP_SUCCESS;
do
{
// Validate "ssp"
if ((ssp != SSP0) &&
(ssp != SSP1))
{
nResult = VGXSSP_INVALID_SSP;
break;
}
if (!m_SSPInfo[ssp].Active)
{
// Already "closed"
break;
}
// Disable SSP logic.
DWORD value = 0;
value = FIELD_SET(value, SSP_0_CONTROL_1, STATUS, DISABLE);
value = FIELD_SET(value, SSP_0_CONTROL_1, OVERRUN_INTERRUPT, DISABLE);
value = FIELD_SET(value, SSP_0_CONTROL_1, TRANSMIT_INTERRUPT, DISABLE);
value = FIELD_SET(value, SSP_0_CONTROL_1, RECEIVE_INTERRUPT, DISABLE);
pokeRegisterDWord(m_SSPInfo[ssp].dwControl1Reg, value);
// Unregister the interrupt routine.
DisableHandler(m_SSPInfo[ssp].dwIntMask);
switch (ssp)
{
case SSP0:
{
// Disable the power gate.
if (!m_SSPInfo[SSP1].Active)
{
value = peekRegisterDWord(CURRENT_POWER_GATE);
value = FIELD_SET(value, CURRENT_POWER_GATE, SSP0_SSP1, DISABLE);
setPower(value, peekRegisterDWord(CURRENT_POWER_CLOCK));
}
// Restore GPIO pins.
value = peekRegisterDWord(GPIO_MUX_HIGH);
value = FIELD_SET(value, GPIO_MUX_HIGH, 32, GPIO); // 0: TXD
value = FIELD_SET(value, GPIO_MUX_HIGH, 33, GPIO); // 0: RXD
value = FIELD_SET(value, GPIO_MUX_HIGH, 34, GPIO); // 0: SFRMOUT
value = FIELD_SET(value, GPIO_MUX_HIGH, 35, GPIO); // 0: SFRMIN
value = FIELD_SET(value, GPIO_MUX_HIGH, 36, GPIO); // 0: SCLKOUT
pokeRegisterDWord(GPIO_MUX_HIGH, value);
}
break;
case SSP1:
{
// Disable the power gate.
if (!m_SSPInfo[SSP0].Active)
{
value = peekRegisterDWord(CURRENT_POWER_GATE);
value = FIELD_SET(value, CURRENT_POWER_GATE, SSP0_SSP1, DISABLE);
setPower(value, peekRegisterDWord(CURRENT_POWER_CLOCK));
}
// Restore GPIO pins.
value = peekRegisterDWord(GPIO_MUX_HIGH);
value = FIELD_SET(value, GPIO_MUX_HIGH, 41, GPIO); // 1: TXD
value = FIELD_SET(value, GPIO_MUX_HIGH, 42, GPIO); // 1: RXD
value = FIELD_SET(value, GPIO_MUX_HIGH, 43, GPIO); // 1: SFRMOUT
value = FIELD_SET(value, GPIO_MUX_HIGH, 44, GPIO); // 1: SFRMIN
value = FIELD_SET(value, GPIO_MUX_HIGH, 45, GPIO); // 1: SCLKIN
pokeRegisterDWord(GPIO_MUX_HIGH, value);
}
break;
};
// Delete the receive buffer.
m_SSPInfo[ssp].readBuffer.SetBuffer();
// Reset the flag
m_SSPInfo[ssp].Active = FALSE;
}
while (0);
#endif // DISABLE_INTERRUPT_MANAGEMENT
MESSAGE(MESSAGE_ZONE, (TEXT("-SMI::sspClose\r\n")));
return nResult;
}
///////////////////////////////////////////////////////////////////////////////
// Read data.
ULONG SMI::sspRead(
VGXSSP_ENUM ssp, // SSP number
PBYTE pBuffer, // Read buffer pointer
DWORD dwSize, // Number of bytes to read
DWORD& dwRead) // Number of bytes read
{
MESSAGE(MESSAGE_ZONE, (TEXT("+SMI::sspRead\r\n")));
#ifdef DISABLE_INTERRUPT_MANAGEMENT
ULONG nResult = VGXSSP_NOT_SUPPORTED;
#else
ULONG nResult = VGXSSP_SUCCESS;
do
{
// Validate "ssp".
if ((ssp != SSP0) &&
(ssp != SSP1))
{
nResult = VGXSSP_INVALID_SSP;
break;
}
// Check activity.
if (!m_SSPInfo[ssp].Active)
{
nResult = VGXSSP_NOT_ACTIVE;
break;
}
// Read data
dwSize /= 2;
for (dwRead = 0; dwRead < dwSize; dwRead++)
{
if (m_SSPInfo[ssp].readBuffer.m_bOverrun)
{
nResult = VGXSSP_FIFO_OVERRUN;
break;
}
WORD data;
if (!m_SSPInfo[ssp].readBuffer.GetWord(data, m_SSPInfo[ssp].read_timeout))
{
nResult = VGXSSP_TIMEOUT;
break;
}
((PWORD)pBuffer)[dwRead] = data;
}
}
while (0);
#endif // DISABLE_INTERRUPT_MANAGEMENT
MESSAGE(MESSAGE_ZONE, (TEXT("-SMI::sspRead\r\n")));
return nResult;
}
///////////////////////////////////////////////////////////////////////////////
// Write data.
ULONG SMI::sspWrite(
VGXSSP_ENUM ssp, // SSP number
PBYTE pBuffer, // Write buffer
DWORD dwSize, // Number of bytes to write
DWORD& dwWritten) // Number of bytes written
{
MESSAGE(MESSAGE_ZONE, (TEXT("+SMI::sspWrite\r\n")));
#ifdef DISABLE_INTERRUPT_MANAGEMENT
ULONG nResult = VGXSSP_NOT_SUPPORTED;
#else
ULONG nResult = VGXSSP_SUCCESS;
do
{
// Validate "ssp".
if ((ssp != SSP0) &&
(ssp != SSP1))
{
nResult = VGXSSP_INVALID_SSP;
break;
}
// Check activity.
if (!m_SSPInfo[ssp].Active)
{
nResult = VGXSSP_NOT_ACTIVE;
break;
}
// Set up the transmit buffer.
dwSize >>= 1;
m_SSPInfo[ssp].writeBuffer.SetBuffer(dwSize, (PWORD)pBuffer);
// Enable transmit interrupt.
pokeRegisterDWord(m_SSPInfo[ssp].dwControl1Reg,
FIELD_SET(peekRegisterDWord(m_SSPInfo[ssp].dwControl1Reg),
SSP_0_CONTROL_1, TRANSMIT_INTERRUPT, ENABLE));
// Wait until the transaction is complete.
if (WaitForSingleObject(
m_SSPInfo[ssp].writeEvent,
m_SSPInfo[ssp].write_timeout) == WAIT_TIMEOUT)
{
// Disable the interrupt.
pokeRegisterDWord(m_SSPInfo[ssp].dwControl1Reg,
FIELD_SET(peekRegisterDWord(m_SSPInfo[ssp].dwControl1Reg),
SSP_0_CONTROL_1, TRANSMIT_INTERRUPT, DISABLE));
nResult = VGXSSP_TIMEOUT;
}
// Calculate the number of words written.
dwWritten = dwSize - m_SSPInfo[ssp].writeBuffer.GetLength();
}
while (0);
#endif // DISABLE_INTERRUPT_MANAGEMENT
MESSAGE(MESSAGE_ZONE, (TEXT("-SMI::sspWrite\r\n")));
return nResult;
}
///////////////////////////////////////////////////////////////////////////////
// Resets the read buffer.
ULONG SMI::sspResetBuffer(VGXSSP_ENUM ssp)
{
MESSAGE(MESSAGE_ZONE, (TEXT("+SMI::sspWrite\r\n")));
#ifdef DISABLE_INTERRUPT_MANAGEMENT
ULONG nResult = VGXSSP_NOT_SUPPORTED;
#else
ULONG nResult = VGXSSP_SUCCESS;
do
{
// Validate "ssp".
if ((ssp != SSP0) &&
(ssp != SSP1))
{
nResult = VGXSSP_INVALID_SSP;
break;
}
// Reset the buffer
m_SSPInfo[ssp].readBuffer.Reset();
}
while (0);
#endif // DISABLE_INTERRUPT_MANAGEMENT
MESSAGE(MESSAGE_ZONE, (TEXT("-SMI::sspWrite\r\n")));
return nResult;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -