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; } } }