Part Number:OMAP-L138
Tool/software: Linux
We have three devices on an SPI bus. The master is the OMAP/ARM processor which drives the clock at 2Mhz (this has been verified with an oscilloscope). The two slave devices are on chipselect 2 and 3 on the OMAP. Data is being sent and received successfully. The issue is that the rate at which we are receiving data is an order of magnitude slower than it should be. Instead of reading the data at 3584Hz (our ideal frequency), we are reading it out at 177Hz. When we are not sending/receiving data, I have verified that the polling loop itself is running at 3584Hz. When I turn on the function to read out the data from the devices, each device takes ~5.7 miliseconds to poll and receive the full data stream. The request data size is 32 bytes and the maximum response size from either device is 32 bytes. So a total round trip poll/response is 64 bytes or 512 bits.
We are not using DMA partly because the documentation on how to use DMA is so poor. This may be a solution if there are blocking conditions using the SPI to read data as we are in this instance.
Any thoughts on what the issue may be?
Thank you,
Erik Jones
Supporting information:
--------------------------------------------
Processor: SOMOMAPL138-10-1602QHIR-B
Compiler package: Codesourcery Sourcery G++ Lite version 4.3.3 (Sourcery G++ Lite 2009q1-203)
RootFS: arago
SPI Application Code:
bool SPIController::sendData(spiDevices spiDevice, SPIRequestBase *Command) {
int spiDev = open(spiDeviceTable[spiDevice].deviceName.c_str(), O_RDWR);
int mode = SPI_MODE_0;
int res = 0;
struct spi_ioc_transfer spiControl;
memset(&spiControl, 0, sizeof(spiControl));
setCS(spiDevice, true);
char *xmitBuffer = new char [spiDeviceTable[spiDevice].max_packet_length];
memset(xmitBuffer, 0, spiDeviceTable[spiDevice].max_packet_length);
memcpy(xmitBuffer, Command->getPacketbuffer(), spiDeviceTable[spiDevice].max_packet_length);
char *recvBuffer = new char [spiDeviceTable[spiDevice].max_packet_length];
memset(recvBuffer, 0, spiDeviceTable[spiDevice].max_packet_length);
res = ioctl(spiDev, SPI_IOC_WR_MODE, &mode);
spiControl.tx_buf = (unsigned long)xmitBuffer;
spiControl.rx_buf = (unsigned long)recvBuffer;
spiControl.len = spiDeviceTable[spiDevice].max_packet_length;
spiControl.speed_hz = SPIController::spiClock;
spiControl.cs_change = 0;
spiControl.bits_per_word = 8;
spiControl.delay_usecs = 0;
if(spiDevice == PIM_DATALOGGER)
xmitBuffer[spiDeviceTable[spiDevice].max_packet_length-1] = 0xAA;
res = ioctl(spiDev, SPI_IOC_MESSAGE(1), &spiControl);
//Detect byteshift
if(spiDevice == PIM_PLATFORM && *(recvBuffer + spiDeviceTable[spiDevice].max_packet_length - 1) == 0) {
memmove(recvBuffer+1, recvBuffer, spiDeviceTable[spiDevice].max_packet_length-1);
*recvBuffer = 0;
//Sign extension
if( (*(recvBuffer+1) & 0x80) > 0 )
*recvBuffer = 0xFF;
}
SPIResponseBase *pr = SPIResponseBase::Dispatch(recvBuffer, spiDevice, spiDeviceTable[spiDevice].max_packet_length);
SPIController::currentTelemetry.u16_DatLog_ActiveFile_Index_HB = DataLogController::getFileNum() >> 16;
SPIController::currentTelemetry.u16_DatLog_ActiveFile_Index_LB = DataLogController::getFileNum() & 0xFF;
SPIController::currentTelemetry.u8_ConfigFile_ID = NetworkServerController::getConfigFileID();
SPIController::currentTelemetry.u8_mode = NetworkServerController::getCurrentMode();
SPIController::currentTelemetry.u32_counter++;
SPIController::currentTelemetry = *pr;
close(spiDev);
setCS(spiDevice, false);
delete [] xmitBuffer;
delete [] recvBuffer;
delete pr;
return true;
}
bool SPIController::setCS(spiDevices spiDevice, bool enable) {
std::string devicePin, enableStr;
enableStr = enable ? "0" : "1";
switch (spiDevice) {
case PIM_PLATFORM:
devicePin = SPIController::SPI_CS2;
break;
case PIM_DATALOGGER:
devicePin = SPIController::SPI_CS3;
break;
}
std::string setval_str = "/sys/class/gpio/gpio" + devicePin + "/value";
ofstream setvalgpio(setval_str.c_str()); // open value file for gpio
if (setvalgpio < 0){
cout << " OPERATION FAILED: Unable to set the value of GPIO"<< devicePin <<" ."<< endl;
return false;
}
setvalgpio << enableStr ;//write value to value file
setvalgpio.close();// close value file
return true;
}
Kernel: From ti-dvsdk-omap138-evm 4.02.0.6 - 2.6.33-rc4-psp03.2.0.14
SPI devices on chipselects 2 & 3. Clock set at 2Mhz via hardcoded SPI driver modifiecation. In mach-davinci/board-da850-evm.c:
static struct spi_board_info da850_spi_board_info[] = {
[0] = {
.modalias = "m25p80",
.platform_data = &spi_flash_data,
.mode = SPI_MODE_0,
.max_speed_hz = 2000000, /* max sample rate at 3V */
.bus_num = 1,
.chip_select = 0,
},
/* Programmable Isolation Mount */
[1] = {
.modalias = "spidev",
.mode = SPI_MODE_0,
.max_speed_hz = 2000000, /* max sample rate at 3V */
.bus_num = 1,
.chip_select = 2,
},
[2] = {
.modalias = "spidev",
.mode = SPI_MODE_0,
.max_speed_hz = 2000000, /* max sample rate at 3V */
.bus_num = 1,
.chip_select = 3,
},
};