⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ssp.cpp

📁 SM501基于ARMV4/ARMV4I平台
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		}
		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 + -