Quantcast
Channel: Forums - Recent Threads
Viewing all articles
Browse latest Browse all 262198

RTOS/TMS320F2812: Cannot transmit/receive more than FIFO size (15 words) using SPI (Non-interrupt)

$
0
0

Part Number:TMS320F2812

Tool/software:TI-RTOS

My current setup is - PC(TwinCAT) --> EtherCAT --> ET1100 piggyback --> SPI --> TI DSP

Everything works perfectly when I transmit/receive less than one FIFO buffer full of data bytes. When I want to call the transmit/receive functions in a loop to transmit/receive more than one FIFO buffer of data, it does not work as intended. Please help me identify the problem because I read the code atleast 20 times but cannot see an error. 

There is NO interrupt usage. 

/*
 * SOES Simple Open EtherCAT Slave
 *
 * File    : esc_hw.c
 * Version : 0.9.2
 * Date    : 22-02-2010
 * Copyright (C) 2007-2010 Arthur Ketels
 *
 * SOES is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License version 2 as published by the Free
 * Software Foundation.
 *
 * SOES is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 *
 * As a special exception, if other files instantiate templates or use macros
 * or inline functions from this file, or you compile this file and link it
 * with other works to produce a work based on this file, this file does not
 * by itself cause the resulting work to be covered by the GNU General Public
 * License. However the source code for this file must still be made available
 * in accordance with section (3) of the GNU General Public License.
 *
 * This exception does not invalidate any other reasons why a work based on
 * this file might be covered by the GNU General Public License.
 *
 * The EtherCAT Technology, the trade name and logo "EtherCAT" are the intellectual
 * property of, and protected by Beckhoff Automation GmbH.
 */
/* Device header file */

#include <stdint.h>        /* Includes uint16_t definition                    */
#include <stdbool.h>       /* Includes true/false definition                  */
#include <DSP281x_Device.h>
#include "utypes.h"
#include "esc.h"
#include "esc_coe.h"
#include "CPU.h"                                                               // Local include file

#define ESC_ETHERCAT_READ			0x02
#define ESC_ETHERCAT_READ_WAIT		0x03
#define ESC_ETHERCAT_WRITE			0x04
#define ESC_ETHERCAT_3BYTEADDR		0x06
#define ESC_ETHERCAT_WAIT			0xFF
#define ESC_ETHERCAT_CONTINUE		0x00
#define ESC_ETHERCAT_RDTERMINATE	0xFF


#define CPU_RATE 16.667L // for a 60MHz CPU clock speed
#define DELAY_US(A)  DSP28x_usDelay(((((long double) A * 1000.0L) / (long double)CPU_RATE) - 9.0L) / 5.0L)


/*---------------------------------------------------------------------------------------------------------------------
; F U N C T I O N   D E F I N I T I O N S
;----------------------------------------------------------------------------------------------------------------------
*/


void InitGpio(void)
{

	EALLOW;
//	IER = 0x0000;
//	IFR = 0x0000;

	// Enable the four I/O pins for the SPI interface
	GpioMuxRegs.GPFMUX.bit.SPISIMOA_GPIOF0 = 1;                                // Slave In, Master Out
	GpioMuxRegs.GPFMUX.bit.SPISOMIA_GPIOF1 = 1;                                // Slave Out, Master In
	GpioMuxRegs.GPFMUX.bit.SPICLKA_GPIOF2 = 1;                                 // Serial Clock
	GpioMuxRegs.GPFMUX.bit.SPISTEA_GPIOF3 = 1;                                 // Slave Transmit Enable (SYNC)

	EDIS;
}


void InitSPI(void)
{

	EALLOW;
	// Initialize SPI FIFO registers
	SpiaRegs.SPICCR.bit.SPISWRESET=0; // Reset SPI

	SpiaRegs.SPICCR.bit.SPICHAR = 0x7; // Character Length  = 8

	SpiaRegs.SPICCR.bit.CLKPOLARITY = 1; // Rising edge

	SpiaRegs.SPICTL.bit.SPIINTENA = 1;		// Enabled
	SpiaRegs.SPICTL.bit.TALK = 1;			//
	SpiaRegs.SPICTL.bit.MASTER_SLAVE = 1;	// Master mode
	SpiaRegs.SPICTL.bit.CLK_PHASE = 0;		// 1/2-cycle delay of Clk wrt SPISTEA (0 - no delay, 1 - delay)
	SpiaRegs.SPICTL.bit.OVERRUNINTENA = 1;	// Overrun Interrupt enabled

	//ClkCfgRegs.LOSPCP.all = 0x1; // 0 = sysclk/1 = 200M; 1 = sysclk/2 = 100M

	SpiaRegs.SPISTS.all=0x0000;		// Clear Status bits (TxBufFull,INT, Overrun)
	SpiaRegs.SPIBRR=0x0005;		// Baud Rate = LSPCLK / (SPIBRR+1) [LSPCLK=SysClk/4 by default=50M]
	//---------------------------------------------------------------------------------------------

	SpiaRegs.SPIFFTX.all=0xC022;      	// Enable FIFO's, reset them, set TX FIFO IntLevl = 2,TXINT disabled
	SpiaRegs.SPIFFTX.bit.TXFFIENA = 0;	// Disable TXFF INT

	SpiaRegs.SPIFFRX.all=0x006A;      	// Enable FIFO's, reset them, set RXFFIL= 10(dec)
	SpiaRegs.SPIFFRX.bit.RXFFIL = 0x02;
	SpiaRegs.SPIFFRX.bit.RXFFIENA = 0;	// disable RXFF INT

	//----------------------------------------------------------------------------------------------
	SpiaRegs.SPIFFCT.all=0x00;			// FFTXDLY = 0 (delay btw Tx transfers)
	SpiaRegs.SPIPRI.all=0x0020;			// Stop after transaction complete on EmuStop

	SpiaRegs.SPICCR.bit.SPISWRESET=1;  // Enable SPI

	SpiaRegs.SPIFFTX.bit.TXFIFO=1;		// Reset Tx FIFO
	SpiaRegs.SPIFFRX.bit.RXFIFORESET=1;

	EDIS;
}


/******************************************************************************
 * Function:        void ESC_read(uint16_t address, uint16_t *buf,
 *                                uint16_t len, uint16_t *tALevent))
 *
 * PreCondition:    SPI initialized
 *                  EthetCAT initialized
 *
 * Input:           uint16_t address = EtherCAT register address
 *                  uint16_t *buf = Pointer to write data to
 *                  uint16_t len = Size of data to read
 *
 * Output:          uint16_t *tALevent = Status returned
 *
 * Side Effects:    None
 *
 * Overview:        This is the main EthetCAT read function
 *****************************************************************************/
void ESC_read(uint16_t offset_addr, void *buf, uint16_t len, void *tALevent)
{

	uint16_t i,cmd, numwords = 0, j;
	static uint16_t readval =0;
	uint16_t *ptr = (uint16_t *)0;
	uint16_t readphase[16];  // FIFO=16,Up to 13 words can be read (Addrphase takes 2Addr+1WS)
	uint16_t loop_count = 0;

	ptr = (uint16_t *)tALevent;

	if(len > 0 && len <= 26) //It is only possible to read 26 bytes of payload (+4 bytes of address) at a time from the TI SPI's FIFO
	{
		// Construct Address cmd bytes into 16-bit words for SPI xmission,
		//    SPI xmits MSBit 1st, so must swap bytes in this 16b word for transmission
		// Byte order of READ cmd sequence:
		// Byte 0: A[12:5]
		// Byte 1: A[4:0], 110b   			(110b is 3-byte cmd extension)
		// Byte 2: A[15:13], CMD[2:0], 00b	(011b is READ w/ WS)
		// Byte 3: FFh						(Wait State)
		//cmd = offset_addr & 0x1f
	
		cmd =(offset_addr & 0x1FE0)<<3; // offset_addr[12:5] is 1st address phase byte, shift to upper byte
		cmd |= (((offset_addr & 0x1F) << 3) | ESC_ETHERCAT_3BYTEADDR);
		readphase[0] = cmd;
		numwords++;
		readphase[1] = (offset_addr & 0xE000) | (ESC_ETHERCAT_READ_WAIT <<10) | ESC_ETHERCAT_WAIT;
		numwords++;
	
		for(i=2, j = 0; j<len ; i++, j+=2)   //numwords is in no. of bytes;
		{
			readphase[i] = (uint16_t) ESC_ETHERCAT_CONTINUE;
			numwords++;
		}
		readphase[--i] |= (ESC_ETHERCAT_RDTERMINATE); // set last byte as 0xFF
	
		/*Disable Interrupts*/
		DINT;
	
		for(i = 0; i < numwords; i++)
		{
			while(SpiaRegs.SPISTS.bit.BUFFULL_FLAG == 1);
			SpiaRegs.SPITXBUF = readphase[i] & (0xFF00);
			while(SpiaRegs.SPISTS.bit.BUFFULL_FLAG == 1);
			SpiaRegs.SPITXBUF = ((readphase[i] & (0xFF)) << 8);
			loop_count++;
		}
		if(loop_count != numwords)
		{
	
				asm(" ESTOP0");
				while(1);
		}
	
		CPU_DELAY_US(5);
		j = numwords;
	
	
		while(SpiaRegs.SPIFFRX.bit.RXFFST < j);
		readval = (SpiaRegs.SPIRXBUF) & 0xFF; // Read to tALevent
		*(ptr) = (readval & 0xFF);
		CPU_DELAY_US(5);	//delay before reading next byte
		readval = (SpiaRegs.SPIRXBUF) & 0xFF; // Read to tALevent
		*(ptr) |= ((readval & 0xFF) << 8);
		CPU_DELAY_US(5);	//delay before reading next byte
	
		readval = SpiaRegs.SPIRXBUF; // ignore
		CPU_DELAY_US(5);	//delay before reading next byte
		readval = SpiaRegs.SPIRXBUF; // ignore
		CPU_DELAY_US(5);	//delay before reading next byte
	
		ptr = (uint16_t *)buf;
			for(i=0;((SpiaRegs.SPIFFRX.bit.RXFFST != 0));i++)
			{
				readval = (SpiaRegs.SPIRXBUF) & 0xFF;
				ptr[i]= (readval & 0xFF);
	
				CPU_DELAY_US(2);	//delay before reading next byte
	
				readval = (SpiaRegs.SPIRXBUF) & 0xFF;
				ptr[i] |= (readval & 0xFF)<<8;
	
				CPU_DELAY_US(2);	//delay before reading next byte
	
			}
	
	
		SpiaRegs.SPIFFRX.bit.RXFIFORESET = 0; //reset the FIFO pointer
		SpiaRegs.SPIFFRX.bit.RXFIFORESET = 1; //reenable the FIFO operation
	
		/*Enable Interrupts*/
		EINT;
		CPU_DELAY_US(10);	//delay before reading next byte
	
	}
}


void ESC_readBlock(uint16_t* pData, uint16_t offset_addr,uint16_t numbytes)
{
	uint16_t i = 0, current_bytes = 0;
	if(numbytes & 0x1)
	{
		current_bytes = (numbytes + 0x1); // even align
	}
	else
	{
		current_bytes = numbytes;
	}


	while(current_bytes > 0) // input is actually in bytes
	{
		if( current_bytes >= 26)
		{
			ESC_read(offset_addr + (2*i), (void *) &pData[i], 26, (void *) &ESCvar.ALevent);
			current_bytes -= 26;
			i+= 13; // data is in 16 bits
		}
		else
		{
			ESC_read(offset_addr + (2*i), (void *) &pData[i], current_bytes, (void *) &ESCvar.ALevent);
			current_bytes = 0;
		}
	}
}



/******************************************************************************
 * Function:        void ESC_write(uint16_t address, uint16_t *buf,
 *                                 uint16_t len, uint16_t *tALevent)
 *
 * PreCondition:    SPI initialized
 *                  EthetCAT initialized
 *
 * Input:           uint16_t address = EtherCAT register address
 *                  uint16_t *buf = Pointer read data from
 *                  uint16_t len = Size of data to write
 *
 * Output:          uint16_t *tALevent = Status returned
 *
 * Side Effects:    None
 *
 * Overview:        This is the main EthetCAT write function
 *****************************************************************************/
void ESC_write(uint16_t offset_addr, void *wrdata, uint16_t len, void *tALevent)
{
	uint16_t i, j,cmd, readval, numwords = 0;
	uint16_t wptr,highbyte,lowbyte;
	uint16_t *ptr = (uint16_t *)0;
	uint16_t writephase[16];


	if(len >0 &&  len <= 26) //It is only possible to transmit 26 bytes of payload (+4 bytes of address) at a time from the TI SPI's FIFO
	{
		// Construct Address cmd bytes into 16-bit words for SPI xmission,
		//    SPI xmits MSBit 1st, so must swap bytes in this 16b word for transmission
			// Byte order of READ cmd sequence:
			// Byte 0: A[12:5]
				// Byte 1: A[4:0], 110b   			(110b is 3-byte cmd extension)
				// Byte 2: A[15:13], CMD[2:0], 00b  (110b is 3-byte cmd extension)
				// Byte 3: A[15:13], CMD[2:0], 00b	(100b is READ w/ WS)
				//cmd = offset_addr & 0x1f

		cmd =(offset_addr & 0x1FE0)<<3; // offset_addr[12:5] is 1st address phase byte, shift to upper byte
		cmd |= (((offset_addr & 0x1F) << 3) | ESC_ETHERCAT_3BYTEADDR);
		writephase[0] = cmd;
		numwords++;
		cmd = 0x0000;
		cmd = (((offset_addr & 0xE000) >> 8) | (ESC_ETHERCAT_3BYTEADDR << 2)) << 8;
		cmd |= (((offset_addr & 0xE000) | (ESC_ETHERCAT_WRITE <<10)) >> 8);
		writephase[1] = cmd;
		numwords++;

		ptr = (uint16_t *) wrdata;

		wptr=0;
		for(i=2, j = 0; j < len ; i++, wptr++)
		{
			// Swap Bytes so low-byte goes first since ET110 i/f uses BYTE addressing
			lowbyte = ptr[wptr] << 8;
			j++;
			highbyte = ptr[wptr] >> 8;
			j++;
			writephase[i] = highbyte | lowbyte;
			numwords++;
		}

		/*Disable Interrupts*/
		DINT;


		for(i=0;i<numwords;i++)
		{

			while(SpiaRegs.SPISTS.bit.BUFFULL_FLAG == 1);
			SpiaRegs.SPITXBUF = writephase[i] & (0xFF00);
			while(SpiaRegs.SPISTS.bit.BUFFULL_FLAG == 1);
			SpiaRegs.SPITXBUF = ((writephase[i] & (0xFF)) << 8);

		}

		CPU_DELAY_US(10);

		j = numwords;
		ptr = (uint16_t *)tALevent;

		while(SpiaRegs.SPIFFRX.bit.RXFFST < j);

		readval = (SpiaRegs.SPIRXBUF) & 0xFF;
		*(ptr) = (readval & 0xFF);
		CPU_DELAY_US(2);	//delay before reading next byte
		readval = (SpiaRegs.SPIRXBUF) & 0xFF;
		*(ptr) |= ((readval & 0xFF) << 8);
		CPU_DELAY_US(2);	//delay before reading next byte


		while(SpiaRegs.SPIFFTX.bit.TXFFST != 0);
		SpiaRegs.SPIFFTX.bit.TXFIFO=0;		// Reset Tx FIFO
		SpiaRegs.SPIFFTX.bit.TXFIFO=1;		// Reset Tx FIFO
		SpiaRegs.SPIFFRX.bit.RXFIFORESET=0;
		SpiaRegs.SPIFFRX.bit.RXFIFORESET=1;

		/*Enable Interrupts*/
		EINT;

		CPU_DELAY_US(10);	//delay before reading next byte
	}

}






void ESC_writeBlock(uint16_t* pData, uint16_t offset_addr,uint16_t numbytes)
{
	uint16_t i = 0; //, current_bytes = 0;
	uint16_t temp_value, temp_ALevent, current_bytes;
	current_bytes = numbytes;

	while(current_bytes > 0) // input is actually in bytes
	{
		if( current_bytes >= 26)
		{
			ESC_write (offset_addr + (2*i), (void *) &pData[i], 26, (void *) &ESCvar.ALevent);
			current_bytes -= 26;
			i+= 13; // data is in 16 bits
		}
		else
		{
			if(current_bytes & 0x1)   //Checking if the remaining bytes are ODD
			{
		//		current_bytes = numbytes + 0x1; // even align
				ESC_write (offset_addr+ (2*i), (void *) &pData[i], current_bytes-1, (void *) &ESCvar.ALevent);
				//now send the last byte with extra alignment bytes
				// note that we read the adjacent byte and write it back
				ESC_read (offset_addr+(numbytes-1), (void *)&temp_value, 2, (void *) &temp_ALevent);

				temp_value &= 0xFF00;
				temp_value |= (pData[numbytes-1]) & 0xFF;
				ESC_write (offset_addr+(numbytes-1), (void *)&temp_value, 2, (void *) &temp_ALevent);

			}
			else
			{
				ESC_write (offset_addr + (2*i), (void *) &pData[i], current_bytes, (void *) &ESCvar.ALevent);

			}
			current_bytes = 0;
		}
	}
}




Viewing all articles
Browse latest Browse all 262198

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>