This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

SPI devices collision OMAP L138

Other Parts Discussed in Thread: SYSBIOS

Hello All,

I am using LogicPD Omap L138 SOM on a custom board, SysBios 6.34.2.18, XDCTools 3.23.5.61, StarterWare 1.10.03.03.

I am trying to communicate with two sensors trough SPI0 bus (different CS) over the ARM9 core.

SPI freq is between 1.25Mhz to 10Mhz (the problem remains the same).

The sensors protocol is as follows:

1. GPIO trigger indicated that data can be read, 
2. When data is ready bring CS down (ACTIVE state)
3. Read  2 words (16bit each) from the bus.
4. Wait for 1.

When working with only one device, this works perfectly but when I add the second device here's what happens:

After several milliseconds of good communication with both sensors, one of the devices interrupt occurs before the other finished sending the data so it takes over the CS line and this is the end for the first device communication and the second keeps on running.

Here is the device protocol:

Here is an image from the logic analyzer when things goes sour:

(D0-SCLK, D1-SOMI, D2-SIMO, D3-CS4, D4-VD4, D5-CS5, D6-VD6)

You can see here that D4 doesn't go HIGH anymore and that D5 interrupts D3 in the middle of the communication (Only 1 word was transferred).

I tried using Gate HWI but I keep missing interrupts and the data is corrupted.

I don't know how to make D5 wait for D3 to finish, I tried making D3 finish the job before\after D5 work, that makes D4 go HIGH again but I miss interrupts again and the data is corrupted.

Here is some of my code (consider it working compiled code):

Void InitSpi0(Void)
{
	/* Enable power to SPI0.													*/
	PSCModuleControl( SOC_PSC_0_REGS			,
			HW_PSC_SPI0				,
			PSC_POWERDOMAIN_ALWAYS_ON	,
			PSC_MDCTL_NEXT_ENABLE )									;

	/*
	 * NOTE: GP0[14] <-> J5p4 <-> SENSOR #1p1-MCLK, set PINMUX0, bit #7 : {GP0[14],I/O}
	 * 		 GP0[09] <-> J6p8 <-> SENSOR #2p10-VD, set PINMUX0, bit #9 : {GP0[09],I/O}
	 * 		 GP0[10] <-> J6p4 <-> SENSOR #2p1-MCLK, set PINMUX0, bit #23: {GP0[10],I/O}		*/
	HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(0))  = 0x08800080					;

	/* force GP0[14] as output, clear the bit									*/
	GPIODirModeSet(SOC_GPIO_0_REGS, SENS0_RST_PIN, GPIO_DIR_OUTPUT)				;

	/* force GP0[10] as output, clear the bit									*/
	GPIODirModeSet(SOC_GPIO_0_REGS, SENS1_RST_PIN, GPIO_DIR_OUTPUT)				;

	/* force GP0[14] set to high												*/
	GPIOPinWrite  (SOC_GPIO_0_REGS, SENS0_RST_PIN, GPIO_PIN_HIGH  )				;

	/* force GP0[10] set to high												*/
	GPIOPinWrite  (SOC_GPIO_0_REGS, SENS1_RST_PIN, GPIO_PIN_HIGH  )				;

	/*
	 * NOTE: GP2[15] <-> J5p6 <-> SENSOR #1p10-VD, set PINMUX5, bit #3: {GP2[15],I/O}
	 */
	HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(5)) |=	0x00000008					;

	/* force GP2[15] as input													*/
	GPIODirModeSet(SOC_GPIO_0_REGS, SENS0_VD_PIN, GPIO_DIR_INPUT )				;

	/* force GP2[14] as input													*/
	GPIODirModeSet(SOC_GPIO_0_REGS, SENS1_VD_PIN, GPIO_DIR_INPUT )				;

	/* Configure rising edge and falling edge triggers on pin GP2[15]
	 * to generate interrupt													*/
	GPIOIntTypeSet(SOC_GPIO_0_REGS, SENS0_VD_PIN, GPIO_INT_TYPE_FALLEDGE) 		;

	/* Configure rising edge and falling edge triggers on pin GP0[09]
	 * to generate interrupt													*/
	GPIOIntTypeSet(SOC_GPIO_0_REGS, SENS1_VD_PIN, GPIO_INT_TYPE_FALLEDGE) 		;

	/* Performing the Pin Multiplexing for SPI #0:
	 * enable pins: {SPI0_CLK, _SPI0_SIMO, SPI0_SOMI, SPI0_ENA} 				*/
	SPIPinMuxSetup(0)															;

	/* select Chip Select(CS) 5 of SPI0											*/
	SPI0CSPinMuxSetup(SENS0_CS)													;

	/* select Chip Select(CS) 4 of SPI0											*/
	SPI0CSPinMuxSetup(SENS1_CS)													;

	/* Configuring and enabling the SPI1 instance. 								*/
	SetupSpi()																	;

	Error_Block eb;
	Error_init(&eb);
	myHwi = Hwi_create(SYS_INT_SPINT0, SPIIsr, NULL, &eb);
	if (myHwi == NULL) {
		System_abort("Hwi create failed");
	}
}


/*
 ** Configures SPI Controller
 **
 */
Void SetupSpi(Void)
{
	unsigned char 	dcs 		= SENS0_CS_WRD | SENS1_CS_WRD					;
	unsigned int	frmt_ind	= SPI_DATA_FORMAT0								;
	// SPI0_CS[0x30]

	/* reset state SPI0, SPI_BASE = 0x01C41000 (for SPI #0)						*/
	SPIReset(SPI_BASE)															;

	/* out of reset state SPI0													*/
	SPIOutOfReset(SPI_BASE)														;

	/* set SPI0 to MASTER_MODE and SPIx_CLK is configured to output				*/
	SPIModeConfigure(SPI_BASE, SPI_MASTER_MODE)									;

	/* set SPI_DATA_FORMAT0.PRESCALARE = (moduleClk/spiClk) - 1, other bits of
	 * SPI_DATA_FORMAT0 are cleared.											*/
	SPIClkConfigure( SPI_BASE		   		,
			ARM_CLK_RATE_IN_HZ>>1	,
			SPI_CLK_RATE_IN_HZ		,
			SPI_DATA_FORMAT0 ) 										;

	/* set SPIPC0 with val: CS#5 active, SPI0_ENA not active (GPIO),
	 * {CLKFUN, SIMOFUN, SOMIFUN, ENAFUN} active 								*/
	//SPIPinControl(SPI_BASE, 0, 0, &val)											;
	HWREG(SPI_BASE + SPI_SPIPC(0))  = 0x0 										;
	HWREG(SPI_BASE + SPI_SPIPC(0)) |= SPIPC0_SOMIFUN_MSK(1)						;
	HWREG(SPI_BASE + SPI_SPIPC(0)) |= SPIPC0_SIMOFUN_MSK(1)						;
	HWREG(SPI_BASE + SPI_SPIPC(0)) |= SPIPC0_CLKFUN_MSK(1)						;
	HWREG(SPI_BASE + SPI_SPIPC(0)) |= SPIPC0_SCS0FUN_MSK(dcs)					;

	/* set SPIDEF with dcs: CS#5 and CS#4 defualt "1" logic when inactive  		*/
	SPIDefaultCSSet(SPI_BASE, dcs)												;

	/*
	 * set SPI_DATA_FORMAT0.POLARITY = 1, SPI clock signal is high-inactive.
	 * set SPI_DATA_FORMAT0.SHIFTDIR = 0, MSB shift out first.
	 * set SPI_DATA_FORMAT0.CHARLEN  = 0x10, 16 bit shift register. 			*/
	SPIConfigDataFmtReg(frmt_ind)												;

	/* set SPI_SPILVL.TXINTLVL = 1, tx interrupt mapped to INT1.
	 * set SPI_SPILVL.RXINTLVL = 1, rx interrupt mapped to INT1.				*/
	SPIIntLevelSet( SPI_BASE,
			SPI_RECV_INTLVL | SPI_TRANSMIT_INTLVL) 						;

	/* set SPI_SPIPC1.SCS0DIR[4] = 1, SPI0_SCS[4] pin is an output.
	 * set SPI_SPIPC1.SCS0DIR[5] = 1, SPI0_SCS[5] pin is an output.
	 * set SPI_SPIPC1.SPIx_CLK   = 1, SPI0_CLK pin is an output.
	 * set SPI_SPIPC1.SIMODIR	 = 1, SPI0 SIMO pin is output.					*/
	//HWREG(SPI_BASE + SPI_SPIPC(1)) |= 0x00000600										;

	/* set SPI_SPIGCR1.ENABLE = 1, Enable SPI0 communication. 					*/
	SPIEnable( SPI_BASE )														;
}

void ReceiveDataNoEdma(unsigned int baseAdd, unsigned short length, short *buffer, UInt8 *read, UInt64 *idx)
{
	int i;
	for(i=0;i<length;i++)
	{
		//while((HWREG(baseAdd + SPI_SPIBUF) & SPI_SPIBUF_TXFULL));
		SPITransmitData1(baseAdd, 0);
		while(!(HWREG(baseAdd + SPI_SPIBUF) & SPI_SPIBUF_RXEMPTY));
	    *buffer = (short)SPIDataReceive(baseAdd);
	    buffer++;
	    (*read)--;
	    (*idx)++;
	}
}

/*
** Send SPI command to slave
**
*/
void SendCommand(unsigned int baseAdd, unsigned char cs, unsigned short command)
{
	SPIDat1Config(baseAdd, (SPI_CSHOLD | SPI_DATA_FORMAT0), (1<<cs));
	while((HWREG(baseAdd + SPI_SPIBUF) & SPI_SPIBUF_TXFULL));
	SPITransmitData1(baseAdd, command);
	SPIDat1Config(baseAdd, SPI_DATA_FORMAT0, (1<<cs));
}

/*
** Configures Data Format register of SPI
**
*/
static void SPIConfigDataFmtReg(unsigned int dataFormat)
{
    /* Configures the polarity and phase of SPI clock */
    SPIConfigClkFormat(SPI_BASE,
                       (SPI_CLK_POL_HIGH | SPI_CLK_INPHASE),
                       dataFormat);

    /* Configures SPI to transmit MSB bit First during data transfer */
    SPIShiftMsbFirst(SPI_BASE, dataFormat);

    /* Sets the Charcter length */
    SPICharLengthSet(SPI_BASE, CHAR_LENGTH, dataFormat);
}

void GPIOBank2Isr(void)
{
	/* Clears the system interrupt status of GPIO in AINTC.*/
	IntSystemStatusClear(SYS_INT_GPIOB2);

	GPIOPinIntClear(SOC_GPIO_0_REGS, SENS0_VD_PIN);
	if(isAvail0) Read0(2, FALSE);
}

void GPIOBank0Isr(void)
{
	/* Clears the system interrupt status of GPIO in AINTC.*/
	IntSystemStatusClear(SYS_INT_GPIOB0);

	GPIOPinIntClear(SOC_GPIO_0_REGS, SENS1_VD_PIN);
	if(isAvail1) Read1(2, FALSE);
}

Int8 Read0(UInt16 length, Bool isSecond)
{
	if(length==0) return 1;
	short *buff;
	readA = length;

	// Check if other sensor is at work
	/*unsigned long csStat = HWREG(SENS1_SPI_REGS + SPI_SPIPC(2));
	Bool isActive = !(HWREG(SENS1_SPI_REGS + SPI_SPIPC(2)) & (1 << SENS1_CS));
	if(isActive && readB>0)
	{
		errB++;
		Read1(readB, TRUE);
	}*/

	//gateKey = GateHwi_enter(gateHwi0);
	SPIDat1Config(SENS0_SPI_REGS, (SPI_CSHOLD |SPI_DATA_FORMAT0), (1<<SENS0_CS));
	ReceiveDataNoEdma(SENS0_SPI_REGS, length, &buff[current], &readA, &idxA);
	NOP;
	SPIDat1Config(SENS0_SPI_REGS, (SPI_DATA_FORMAT0), (1<<SENS0_CS));
	//GateHwi_leave(gateHwi0, gateKey);
}

Int8 Read1(UInt16 length, Bool isSecond)
{
	if(length==0) return 1;
	short *buff;
	readB = length;

	// Check if other sensor is at work
	/*unsigned long csStat = HWREG(SENS0_SPI_REGS + SPI_SPIPC(2));
    	Bool isActive = !(HWREG(SENS0_SPI_REGS + SPI_SPIPC(2)) & (1 << SENS0_CS));
    	if(isActive && readA>0)
    	{
    		errA++;
    		Read0(readA, TRUE);
    	}*/

	//gateKey = GateHwi_enter(gateHwi0);
	SPIDat1Config(SENS1_SPI_REGS, (SPI_CSHOLD | SPI_DATA_FORMAT0), (1<<SENS1_CS));
	ReceiveDataNoEdma(SENS1_SPI_REGS, length, &buff[current], &readB, &idxB);
	NOP;
	SPIDat1Config(SENS1_SPI_REGS, (SPI_DATA_FORMAT0), (1<<SENS1_CS));
	//GateHwi_leave(gateHwi0, gateKey);
}

The devices are a black box and cannot be changed, I can start the streaming at different times but eventually the same thing happens.

Why is it taking 15us for the SPI to start the transfer after the GPIO trigger (I checked and the code doesn't take so long)?

Sorry for the long post but I'm really frustrated so I would appreciate your help.

Thanks,
Yoel

  • Hi,

    Team is working on this and will let you know the update.

    Thanks & regards,

    Sivaraj K

  • Hi Yoel,

    Would you please post your interface diagram for SPI communication?

     

    Regards,

    Shankari

  • Hi Shankari,

    What do you mean by interface diagram?

    Yoel

  • Hi yoel,

    Would you please post the portion of your schematic diagram which contains the interface of Sensor devices with the processor.

     

    Regards,

    Shankari

  • Do you mean the electrical schematics?

    This is my schematic but instead of SPI1 lines, I changed it to SPI0:

    Yoel

  • Hi Yoel,

    To find that the transaction with the slave device is completed, we can consider checking the values of "CSNR fields" of 'SPI Data Register 1' and then start the communication with the next sensor.

    Yoel said:
    Why is it taking 15us for the SPI to start the transfer after the GPIO trigger (I checked and the code doesn't take so long)?

    While configuring SPI, did you use "SPI Delay Register" and set C2TDELAY field?

     

    Regards,

    Shankari.

  • Hi Shankari,

    As you can see in my code, commented, is my try to find out if the other device is in the middle of communication (I check the SPIPC2 registers, is that wrong?) My problem there is that I don't know how to wait untill the end of the communication (This is HWI so I can't call Task_sleep and I can't ignore this call because I will miss it).

    I did play a little with the delay function but right now it is set to zero and the delay happens between the GPIO ISR and the Active state of CS, not between the CS down and start of communication, in other words, my question is, How can I make the GPIO interrupt fire the ISR without delay?

    Thanks,
    Yoel

  • Yoel,

    Can you please specify your SYSBIOS setup for the code. I understand you have GPIO ISr as the HWIs.  Also specify the priorities assigned. The setup is complicating matters as it is connected to the same SPI on a different chipselect

    It seems like you need a more efficient way to handle your interrupts but there would still be possible to have data corruptions because you are sharing same piece of hardware.  Is there any reason you choose to use both the sensors on the same SPI and with different chip selects. Having them on different SPI could help you avoid this conflict.

  • Hi Rahul,

    Here is the SysBios config:

    var BIOS 		= xdc.useModule('ti.sysbios.BIOS'); 
    var Mmu 		= xdc.useModule('ti.sysbios.family.arm.arm9.Mmu');
    var System      = xdc.useModule('xdc.runtime.System');
    var SysStd      = xdc.useModule('xdc.runtime.SysStd');
    var Notify      = xdc.useModule('ti.sdo.ipc.Notify');
    var Task 		= xdc.useModule('ti.sysbios.knl.Task');
    var Semaphore   = xdc.useModule('ti.sysbios.knl.Semaphore');
    var NotifySetup = xdc.useModule('ti.sdo.ipc.family.da830.NotifySetup');
    var Hwi 		= xdc.useModule('ti.sysbios.hal.Hwi');
    var Exception = xdc.useModule('ti.sysbios.family.arm.exc.Exception');
    var Cache = xdc.useModule('ti.sysbios.hal.Cache');
    Cache.CacheProxy = xdc.useModule('ti.sysbios.hal.CacheNull');
    var Timestamp = xdc.useModule('xdc.runtime.Timestamp');
    var GateHwi = xdc.useModule('ti.sysbios.gates.GateHwi');
    
    System.SupportProxy = SysStd;
    
    Mmu.enableMMU = false;
    
    /* System stack size (used by ISRs and Swis) */
    Program.stack = 0x8000;
    
    var task0Params = new Task.Params();
    task0Params.instance.name = "tsk0";
    Program.global.tsk0 = Task.create("&tsk0_func", task0Params);
    var task2Params = new Task.Params();
    task2Params.instance.name = "tsk2";
    Program.global.tsk2 = Task.create("&tsk2_func", task2Params);
    
    Mmu.enableMMU = false;
    
    /*
    var hwi0Params = new Hwi.Params();
    hwi0Params.instance.name = "hwi0";
    Program.global.hwi0 = Hwi.create(20, "&SPIIsr", hwi0Params); // SPI0
    //Program.global.hwi0 = Hwi.create(56, "&SPIIsr", hwi0Params); // SPI1
    */
    var hwi1Params = new Hwi.Params();
    hwi1Params.instance.name = "hwi1";
    hwi1Params.priority = -1;
    Program.global.hwi1 = Hwi.create(44, "&GPIOBank2Isr", hwi1Params);
    
    var hwi5Params = new Hwi.Params();
    hwi5Params.instance.name = "hwi5";
    hwi5Params.priority = -1;
    Program.global.hwi5 = Hwi.create(42, "&GPIOBank0Isr", hwi5Params);
    
    var hwi4Params = new Hwi.Params();
    hwi4Params.instance.name = "i2c0";
    Program.global.i2c0 = Hwi.create(15, "&I2C0Isr", hwi4Params);
    
    var semaphore2Params = new Semaphore.Params();
    semaphore2Params.instance.name = "sLeft";
    semaphore2Params.mode = Semaphore.Mode_BINARY;
    Program.global.sLeft = Semaphore.create(null, semaphore2Params);
    var semaphore3Params = new Semaphore.Params();
    semaphore3Params.instance.name = "sRight";
    semaphore3Params.mode = Semaphore.Mode_BINARY;
    Program.global.sRight = Semaphore.create(null, semaphore3Params);
    var gateHwi0Params = new GateHwi.Params();
    gateHwi0yParams.instance.name = "gateHwi0";
    Program.global.gateHwi0 = GateHwi.create(gateHwi0Params);
    

    I don't use the SPI interrupts (It takes too long) and the GPIO HWI priorities are -1, otherwise it doesn't work.

    About the SPI buses, let me reffer you to another unresolved post of mine, I have problems with SPI1 and LogicPD doesn't want to help unless I pay them a ransom of 5000$ so if I can't find a solution to this problem I will be forced to pay (problem number 1):

    http://e2e.ti.com/support/dsp/omap_applications_processors/f/42/p/345403/1207911.aspx#1207911

    I still don't know why is it taking so long for the HWI ISR to fire, maybe there lays the solution.

    Thanks,

    Yoel

  • Yoel,

    SPI is a shared resource, have you tried using GateMutex to block access by any other tasks when it is being used by a task? I mean if SPIread0 and SPIread1 are implemented as tasks with a GateMutex that they pend on even if the GPIO interrupt fires they wont be able to start a SPI read unless they acquire the mutex. This will prevent you from missing the ISR as well as esure that a SPI read will continue till execution before the next SPI read starts. I am not a SYSBIOS expert but I thing this should work.

    Regards,

    Rahul

    PS

    What happens if you change the HWI priorities ? If you are having issue changing priorities a SYSBIOS expert may be able to help you with any issue that you may be running into.

     

  • Hi Rahul,

    I did as you suggested, not the flow is as follows:

    void GPIOBank2Isr(void)
    {
    	/* Clears the system interrupt status of GPIO in AINTC.*/
    	IntSystemStatusClear(SYS_INT_GPIOB2);
    
    	if(GPIOPinIntStatus(SOC_GPIO_0_REGS, SENS0_VD_PIN) == GPIO_INT_PEND)
    	{
    		/* Clears the Interrupt Status of the correct pin in GPIO.*/
    		GPIOPinIntClear(SOC_GPIO_0_REGS, SENS0_VD_PIN);
    		if(isAvail0)
    		{
    			Semaphore_post(semHwi0);
    		}
    	}
    }
    
    void GPIOBank0Isr(void)
    {
    	/* Clears the system interrupt status of GPIO in AINTC.*/
    	IntSystemStatusClear(SYS_INT_GPIOB0);
    
    	if(GPIOPinIntStatus(SOC_GPIO_0_REGS, SENS1_VD_PIN) == GPIO_INT_PEND)
    	{
    		/* Clears the Interrupt Status of the correct pin in GPIO.*/
    
    		GPIOPinIntClear(SOC_GPIO_0_REGS, SENS1_VD_PIN);
    		if(isAvail1)
    		{
    			Semaphore_post(semHwi1);
    		}
    	}
    }
    
    Void Read0(Void)
    {
    	while(1)
    	{
    		short *buff = (short*)RxBuffA;
    		int current = idxA % BUFFER_SIZE_16;
    		Semaphore_pend(semHwi0, BIOS_WAIT_FOREVER);
    
    		UInt16 length=2;
    		readA = length;
    
    		gateKey = GateMutex_enter(gateMutex0);
    		SPIDat1Config(SENS0_SPI_REGS, (SPI_CSHOLD |SPI_DATA_FORMAT0), (1<<SENS0_CS));
    		ReceiveDataNoEdma(SENS0_SPI_REGS, length, &buff[current], &readA, &idxA);
    		Nop(1);
    		SPIDat1Config(SENS0_SPI_REGS, (SPI_DATA_FORMAT0), (1<<SENS0_CS));
    		GateMutex_leave(gateMutex0, gateKey);
    	}
    }
    
    Void Read1(Void)
    {
    	while(1)
    	{
    		short *buff = (short*)RxBuffB;
    		int current = idxB % BUFFER_SIZE_16;
    		Semaphore_pend(semHwi1, BIOS_WAIT_FOREVER);
    		UInt16 length=2;
    		readB = length;
    
    		gateKey = GateMutex_enter(gateMutex0);
    		SPIDat1Config(SENS1_SPI_REGS, (SPI_CSHOLD | SPI_DATA_FORMAT0), (1<<SENS1_CS));
    		ReceiveDataNoEdma(SENS1_SPI_REGS, length, &buff[current], &readB, &idxB);
    		Nop(1);
    		SPIDat1Config(SENS1_SPI_REGS, (SPI_DATA_FORMAT0), (1<<SENS1_CS));
    		GateMutex_leave(gateMutex0, gateKey);
    	}
    }

    Config file:

    var BIOS 		= xdc.useModule('ti.sysbios.BIOS'); 
    var Mmu 		= xdc.useModule('ti.sysbios.family.arm.arm9.Mmu');
    var System      = xdc.useModule('xdc.runtime.System');
    var SysStd      = xdc.useModule('xdc.runtime.SysStd');
    var Notify      = xdc.useModule('ti.sdo.ipc.Notify');
    var Task 		= xdc.useModule('ti.sysbios.knl.Task');
    var Semaphore   = xdc.useModule('ti.sysbios.knl.Semaphore');
    var NotifySetup = xdc.useModule('ti.sdo.ipc.family.da830.NotifySetup');
    var Hwi 		= xdc.useModule('ti.sysbios.hal.Hwi');
    var Exception = xdc.useModule('ti.sysbios.family.arm.exc.Exception');
    var Cache = xdc.useModule('ti.sysbios.hal.Cache');
    Cache.CacheProxy = xdc.useModule('ti.sysbios.hal.CacheNull');
    var Timestamp = xdc.useModule('xdc.runtime.Timestamp');
    var GateHwi = xdc.useModule('ti.sysbios.gates.GateHwi');
    var GateMutex = xdc.useModule('ti.sysbios.gates.GateMutex');
    
    System.SupportProxy = SysStd;
    
    Mmu.enableMMU = false;
    
    /* System stack size (used by ISRs and Swis) */
    Program.stack = 0x8000;
    
    var task0Params = new Task.Params();
    task0Params.instance.name = "tsk0";
    task0Params.priority = 1;
    Program.global.tsk0 = Task.create("&tsk0_func", task0Params);
    var task2Params = new Task.Params();
    task2Params.instance.name = "tsk2";
    task2Params.priority = 1;
    Program.global.tsk2 = Task.create("&tsk2_func", task2Params);
    
    
    Mmu.enableMMU = false;
    
    var hwi1Params = new Hwi.Params();
    hwi1Params.instance.name = "hwi1";
    hwi1Params.priority = 2;
    Program.global.hwi1 = Hwi.create(44, "&GPIOBank2Isr", hwi1Params);
    
    var hwi5Params = new Hwi.Params();
    hwi5Params.instance.name = "hwi5";
    hwi5Params.priority = 2;
    Program.global.hwi5 = Hwi.create(42, "&GPIOBank0Isr", hwi5Params);
    
    var hwi4Params = new Hwi.Params();
    hwi4Params.instance.name = "i2c0";
    Program.global.i2c0 = Hwi.create(15, "&I2C0Isr", hwi4Params);
    
    var semaphore2Params = new Semaphore.Params();
    semaphore2Params.instance.name = "sLeft";
    semaphore2Params.mode = Semaphore.Mode_BINARY;
    Program.global.sLeft = Semaphore.create(null, semaphore2Params);
    var semaphore3Params = new Semaphore.Params();
    semaphore3Params.instance.name = "sRight";
    semaphore3Params.mode = Semaphore.Mode_BINARY;
    Program.global.sRight = Semaphore.create(null, semaphore3Params);
    var gateHwi0Params = new GateHwi.Params();
    gateHwi0Params.instance.name = "gateHwi0";
    Program.global.gateHwi0 = GateHwi.create(gateHwi0Params);
    var gateMutex0Params = new GateMutex.Params();
    gateMutex0Params.instance.name = "gateMutex0";
    Program.global.gateMutex0 = GateMutex.create(gateMutex0Params);
    var semaphore2Params0 = new Semaphore.Params();
    semaphore2Params0.instance.name = "semHwi0";
    semaphore2Params0.mode = Semaphore.Mode_BINARY;
    Program.global.semHwi0 = Semaphore.create(null, semaphore2Params0);
    var semaphore3Params0 = new Semaphore.Params();
    semaphore3Params0.instance.name = "semHwi1";
    semaphore3Params0.mode = Semaphore.Mode_BINARY;
    Program.global.semHwi1 = Semaphore.create(null, semaphore3Params0);
    var task2Params0 = new Task.Params();
    task2Params0.instance.name = "tsk_sens0";
    task2Params0.priority = 2;
    Program.global.tsk_sens0 = Task.create("&Read0", task2Params0);
    var task3Params = new Task.Params();
    task3Params.instance.name = "tsk_sens1";
    task3Params.priority = 2;
    Program.global.tsk_sens1 = Task.create("&Read1", task3Params);
    

    As you can see in the image below, the time it takes between the VD (GPIO ISR) to the CS active is almost 50us, all it has to do is release from the Semaphore pend.

    Changing the Hwi didn't solve the problem.

    Thanks,
    Yoel

  • OK, I somehow made SPI1 work correctly with the sensors and now I have each sensor on a different SPI bus.

    But, the problem remain the same... At some point for one of the devices (not always the same one) the MCU takes a long time to do the transmission and the device stops streaming data. It's really weird, they don't share the same resources except for the ARM processor and they still can't work together...

    Any ideas?

    Thanks,
    Yoel 

  • Hurray!!!

    I switched to xdctools_3_24_07_73 and bios_6_35_04_50 and it solved the problem.

    Don't know why...

    I will try again with both sensors on SPI0 bus to see if the problem is solved there too and give an update.

    Yoel

  • Rahul,

    I tought that the problem is behind me but I guess I was wrong.

    Everything works grate if all the program does is the sensor SPI reads (stuck in a while loop), if I put a little Task_sleep(1) inside the while loop, I get the same problem again (one of the sensors stop streaming data).

    I now use SWI as the handler for the SPI transmissions.

    Here is some of the code:

    Config file:

    var BIOS 		= xdc.useModule('ti.sysbios.BIOS'); 
    var Mmu 		= xdc.useModule('ti.sysbios.family.arm.arm9.Mmu');
    var System      = xdc.useModule('xdc.runtime.System');
    var SysStd      = xdc.useModule('xdc.runtime.SysStd');
    var Notify      = xdc.useModule('ti.sdo.ipc.Notify');
    var Task 		= xdc.useModule('ti.sysbios.knl.Task');
    var Semaphore   = xdc.useModule('ti.sysbios.knl.Semaphore');
    var NotifySetup = xdc.useModule('ti.sdo.ipc.family.da830.NotifySetup');
    var Hwi 		= xdc.useModule('ti.sysbios.hal.Hwi');
    var Exception = xdc.useModule('ti.sysbios.family.arm.exc.Exception');
    var Cache = xdc.useModule('ti.sysbios.hal.Cache');
    Cache.CacheProxy = xdc.useModule('ti.sysbios.hal.CacheNull');
    var Timestamp = xdc.useModule('xdc.runtime.Timestamp');
    var Swi = xdc.useModule('ti.sysbios.knl.Swi');
    
    System.SupportProxy = SysStd;
    
    Mmu.enableMMU = false;
    
    /* System stack size (used by ISRs and Swis) */
    Program.stack = 0x8000;
    
    var task0Params = new Task.Params();
    task0Params.instance.name = "tsk0";
    task0Params.priority = 1;
    Program.global.tsk0 = Task.create("&tsk0_func", task0Params);
    var task2Params = new Task.Params();
    task2Params.instance.name = "tsk2";
    task2Params.priority = 1;
    Program.global.tsk2 = Task.create("&tsk2_func", task2Params);
    
    var hwi1Params = new Hwi.Params();
    hwi1Params.instance.name = "hwi1";
    hwi1Params.priority = -1;
    Program.global.hwi1 = Hwi.create(44, "&GPIOBank2Isr", hwi1Params);
    
    var hwi5Params = new Hwi.Params();
    hwi5Params.instance.name = "hwi5";
    hwi5Params.priority = -1;
    Program.global.hwi5 = Hwi.create(42, "&GPIOBank0Isr", hwi5Params);
    
    var swi0Params = new Swi.Params();
    swi0Params.instance.name = "swi0";
    swi0Params.priority = 2;
    Program.global.swi0 = Swi.create("&Read0", swi0Params);
    var swi1Params = new Swi.Params();
    swi1Params.instance.name = "swi1";
    swi1Params.priority = 2;
    Program.global.swi1 = Swi.create("&Read1", swi1Params);

    SPI handler:

    void GPIOBank2Isr(void)
    {
    	/* Clears the system interrupt status of GPIO in AINTC.*/
    	IntSystemStatusClear(SYS_INT_GPIOB2);
    
    	if(GPIOPinIntStatus(SOC_GPIO_0_REGS, SENS0_VD_PIN) == GPIO_INT_PEND)
    	{
    		/* Clears the Interrupt Status of the correct pin in GPIO.*/
    		GPIOPinIntClear(SOC_GPIO_0_REGS, SENS0_VD_PIN);
    		if(isAvail0)
    		{
    			Swi_post(swi0);
    		}
    	}
    }
    
    void GPIOBank0Isr(void)
    {
    	/* Clears the system interrupt status of GPIO in AINTC.*/
    	IntSystemStatusClear(SYS_INT_GPIOB0);
    
    	if(GPIOPinIntStatus(SOC_GPIO_0_REGS, SENS1_VD_PIN) == GPIO_INT_PEND)
    	{
    		/* Clears the Interrupt Status of the correct pin in GPIO.*/
    		GPIOPinIntClear(SOC_GPIO_0_REGS, SENS1_VD_PIN);
    		if(isAvail1)
    		{
    			Swi_post(swi1);
    		}
    	}
    }
    
    Void Read0(Void)
    {
    	short *buff = (short*)RxBuffA;
    	int current = idxA % totalLength;
    	readA = length;
    
    	SPIDat1Config(SENS0_SPI_REGS, (SPI_CSHOLD |SPI_DATA_FORMAT0), (1<<SENS0_CS));
    	SPIReceiveData(SENS0_SPI_REGS, length, &buff[current], &readA, &idxA);
    	SPIDat1Config(SENS0_SPI_REGS, (SPI_DATA_FORMAT0), (1<<SENS0_CS));
    	if(readStateA == GRABFRAME)
    	{
    		if(idxA % FRAME_SIZE_16 == 0)
    		{
    			frameCountA++;
    			if(IsFrameValid(&buff[current-30])==FALSE)
    			{
    				frameErrA++;
    			}
    			Semaphore_post(sLeft);
    		}
    	}
    	else if(idxA >= SIZE_EEPROM)
    	{
    		readStateA = STOPSENSOR;
    		isAvail0 = 0;
    	}
    }
    
    Void Read1(Void)
    {
    	short *buff = (short*)RxBuffB;
    	int current = idxB % totalLength;
    	readB = length;
    
    	SPIDat1Config(SENS1_SPI_REGS, (SPI_CSHOLD | SPI_DATA_FORMAT0), (1<<SENS1_CS));
    	SPIReceiveData(SENS1_SPI_REGS, length, &buff[current], &readB, &idxB);
    	SPIDat1Config(SENS1_SPI_REGS, (SPI_DATA_FORMAT0), (1<<SENS1_CS));
    	if(readStateB == GRABFRAME)
    	{
    		if(idxB % FRAME_SIZE_16 == 0)
    		{
    			frameCountB++;
    			if(IsFrameValid(&buff[current-30])==FALSE)
    			{
    				frameErrB++;
    			}
                 		Semaphore_post(sRight);
    		}
    	}
    	else if(idxB >= SIZE_EEPROM)
    	{
    		readStateB = STOPSENSOR;
    		isAvail1 = 0;
    	}
    }

    SPI Init and control:

    Void InitSpi(Void)
    {
    	/* Enable power to SPI0.													*/
    	PSCModuleControl( SOC_PSC_0_REGS			,
    			HW_PSC_SPI0				,
    			PSC_POWERDOMAIN_ALWAYS_ON	,
    			PSC_MDCTL_NEXT_ENABLE )									;
    
    	/*
    	 * NOTE: GP0[14] <-> J5p4 <-> SENSOR #1p1-MCLK, set PINMUX0, bit #7 : {GP0[14],I/O}
    	 * 		 GP0[09] <-> J6p8 <-> SENSOR #2p10-VD, set PINMUX0, bit #9 : {GP0[09],I/O}
    	 * 		 GP0[10] <-> J6p4 <-> SENSOR #2p1-MCLK, set PINMUX0, bit #23: {GP0[10],I/O}		*/
    	HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(0))  = 0x08800080					;
    
    	/* force GP0[14] as output, clear the bit									*/
    	GPIODirModeSet(SOC_GPIO_0_REGS, SENS0_RST_PIN, GPIO_DIR_OUTPUT)				;
    
    	/* force GP0[10] as output, clear the bit									*/
    	GPIODirModeSet(SOC_GPIO_0_REGS, SENS1_RST_PIN, GPIO_DIR_OUTPUT)				;
    
    	/* force GP0[14] set to high												*/
    	GPIOPinWrite  (SOC_GPIO_0_REGS, SENS0_RST_PIN, GPIO_PIN_HIGH  )				;
    
    	/* force GP0[10] set to high												*/
    	GPIOPinWrite  (SOC_GPIO_0_REGS, SENS1_RST_PIN, GPIO_PIN_HIGH  )				;
    
    	/*
    	 * NOTE: GP2[15] <-> J5p6 <-> SENSOR #1p10-VD, set PINMUX5, bit #3: {GP2[15],I/O}
    	 */
    	HWREG(SOC_SYSCFG_0_REGS + SYSCFG0_PINMUX(5)) |=	0x00000008					;
    
    	/* force GP2[15] as input													*/
    	GPIODirModeSet(SOC_GPIO_0_REGS, SENS0_VD_PIN, GPIO_DIR_INPUT )				;
    
    	/* force GP2[14] as input													*/
    	GPIODirModeSet(SOC_GPIO_0_REGS, SENS1_VD_PIN, GPIO_DIR_INPUT )				;
    
    	/* Configure rising edge and falling edge triggers on pin GP2[15]
    	 * to generate interrupt													*/
    	GPIOIntTypeSet(SOC_GPIO_0_REGS, SENS0_VD_PIN, GPIO_INT_TYPE_FALLEDGE) 		;
    
    	/* Configure rising edge and falling edge triggers on pin GP0[09]
    	 * to generate interrupt													*/
    	GPIOIntTypeSet(SOC_GPIO_0_REGS, SENS1_VD_PIN, GPIO_INT_TYPE_FALLEDGE) 		;
    
    	/* Performing the Pin Multiplexing for SPI #0:
    	 * enable pins: {SPI0_CLK, _SPI0_SIMO, SPI0_SOMI, SPI0_ENA} 				*/
    	SPIPinMuxSetup(0)															;
    
    	/* select Chip Select(CS) 5 of SPI0											*/
    	SPI0CSPinMuxSetup(SENS0_CS)													;
    
    	/* select Chip Select(CS) 4 of SPI0											*/
    	SPI0CSPinMuxSetup(SENS1_CS)													;
    
    	/* Configuring and enabling the SPI1 instance. 								*/
    	//SetupSpi()																	;
    	SetupSpi(SENS0_SPI_BASE, (SENS0_CS_WRD | SENS1_CS_WRD))																	;
    }
    /*
     ** Configures SPI Controller
     **
     */
    Void SetupSpi(unsigned int baseAdd, unsigned char dcs)
    {
    	unsigned int	frmt_ind	= SPI_DATA_FORMAT0								;
    	// SPI0_CS[0x30]
    
    	/* reset state SPI0, SPI_BASE = 0x01C41000 (for SPI #0)						*/
    	SPIReset(baseAdd)															;
    
    	/* out of reset state SPI0													*/
    	SPIOutOfReset(baseAdd)														;
    
    	/* set SPI0 to MASTER_MODE and SPIx_CLK is configured to output				*/
    	SPIModeConfigure(baseAdd, SPI_MASTER_MODE)									;
    
    	/* set SPI_DATA_FORMAT0.PRESCALARE = (moduleClk/spiClk) - 1, other bits of
    	 * SPI_DATA_FORMAT0 are cleared.											*/
    	SPIClkConfigure( baseAdd		   		,
    			ARM_CLK_RATE_IN_HZ>>1	,
    			SPI_CLK_RATE_IN_HZ		,
    			SPI_DATA_FORMAT0 ) 										;
    
    	/* set SPIPC0 with val: CS#5 active, SPI0_ENA not active (GPIO),
    	 * {CLKFUN, SIMOFUN, SOMIFUN, ENAFUN} active 								*/
    	//SPIPinControl(SPI_BASE, 0, 0, &val)											;
    	HWREG(baseAdd + SPI_SPIPC(0))  = 0x0 										;
    	HWREG(baseAdd + SPI_SPIPC(0)) |= SPIPC0_SOMIFUN_MSK(1)						;
    	HWREG(baseAdd + SPI_SPIPC(0)) |= SPIPC0_SIMOFUN_MSK(1)						;
    	HWREG(baseAdd + SPI_SPIPC(0)) |= SPIPC0_CLKFUN_MSK(1)						;
    	HWREG(baseAdd + SPI_SPIPC(0)) |= SPIPC0_SCS0FUN_MSK(dcs)					;
    
    	/* set SPIDEF with dcs: CS#5 and CS#4 defualt "1" logic when inactive  		*/
    	SPIDefaultCSSet(baseAdd, dcs)												;
    
    	/*
    	 * set SPI_DATA_FORMAT0.POLARITY = 1, SPI clock signal is high-inactive.
    	 * set SPI_DATA_FORMAT0.SHIFTDIR = 0, MSB shift out first.
    	 * set SPI_DATA_FORMAT0.CHARLEN  = 0x10, 16 bit shift register. 			*/
    	SPIConfigDataFmtReg(baseAdd, frmt_ind)												;
    
    	/* set SPI_SPILVL.TXINTLVL = 1, tx interrupt mapped to INT1.
    	 * set SPI_SPILVL.RXINTLVL = 1, rx interrupt mapped to INT1.				*/
    	SPIIntLevelSet( baseAdd,
    			SPI_RECV_INTLVL | SPI_TRANSMIT_INTLVL) 						;
    
    	/* set SPI_SPIPC1.SCS0DIR[4] = 1, SPI0_SCS[4] pin is an output.
    	 * set SPI_SPIPC1.SCS0DIR[5] = 1, SPI0_SCS[5] pin is an output.
    	 * set SPI_SPIPC1.SPIx_CLK   = 1, SPI0_CLK pin is an output.
    	 * set SPI_SPIPC1.SIMODIR	 = 1, SPI0 SIMO pin is output.					*/
    	//HWREG(baseAdd + SPI_SPIPC(1)) |= 0x00000600										;
    
    	/* set SPI_SPIGCR1.ENABLE = 1, Enable SPI0 communication. 					*/
    	SPIEnable( baseAdd )														;
    }
    
    /*
     ** Get Data from slave
     **
    */
    void SPIReceiveData(unsigned int baseAdd, unsigned short length, short *buffer, UInt8 *read, UInt64 *idx)
    {
    	int i;
    	for(i=0;i<length;i++)
    	{
    		while(!(HWREG(baseAdd + SPI_SPIFLG) & SPI_SPIFLG_TXINTFLG));
    		SPITransmitData1(baseAdd, 0);
    		while(!(HWREG(baseAdd + SPI_SPIFLG) & SPI_SPIFLG_RXINTFLG));
    		*buffer = (short)SPIDataReceive(baseAdd);
    	    buffer++;
    	    (*read)--;
    	    (*idx)++;
    	}
    }
    
    /*
    ** Send SPI command to slave
    **
    */
    void SPISendCmd(unsigned int baseAdd, unsigned char cs, unsigned short command)
    {
    //#if(USE_SPI_DMA == ON)
    	SPIDat1Config(baseAdd, (SPI_CSHOLD | SPI_DATA_FORMAT0), (1<<cs));
    	while(!(HWREG(baseAdd + SPI_SPIFLG) & SPI_SPIFLG_TXINTFLG));
    	SPITransmitData1(baseAdd, command);
    	while(!(HWREG(baseAdd + SPI_SPIFLG) & SPI_SPIFLG_RXINTFLG));
    	SPIDataReceive(baseAdd);
    	SPIDat1Config(baseAdd, SPI_DATA_FORMAT0, (1<<cs));
    }
    /*
    ** Configures Data Format register of SPI
    **
    */
    void SPIConfigDataFmtReg(unsigned int baseAdd, unsigned int dataFormat)
    {
        /* Configures the polarity and phase of SPI clock */
        SPIConfigClkFormat(baseAdd,
                           (SPI_CLK_POL_HIGH | SPI_CLK_INPHASE),
                           dataFormat);
    
        /* Configures SPI to transmit MSB bit First during data transfer */
        SPIShiftMsbFirst(baseAdd, dataFormat);
    
        /* Sets the Charcter length */
        SPICharLengthSet(baseAdd, CHAR_LENGTH, dataFormat);
    }

    Main:

    Void tsk0_func(UArg arg0, UArg arg1)
    {
            InitSPI();
    	int time = 1;
    	StartStreaming2();
    	while(1)
    	{
    		Task_sleep(time);
    	}
    }

    If time = 0, it works.

    Read0 & Read1 are the SWI ISR.

    SPI0 is used only.

    Any Idea?

    Thanks,
    Yoel

  • Shankari? Rahul?

    I can't use the IPC module anymore because every time I use the Notify function, the streaming stops.
    Also if I use Task_sleep.

    Any suggestions?

    Yoel

  • Yoel,

    Can you please post your IPC question on the TI RTOS forum where the right experts can address the issue.

    Regards,

    Rahul

  • I did:

    http://e2e.ti.com/support/embedded/tirtos/f/355/p/372858/1314369.aspx#1314369

    This is not an IPC problem, maybe sys\bios.
    Not sure yet.

    Yoel

  • Hi Yoel,

    Thank you.

    You would get IPC and SYS/BIOS (RTOS) supports from RTOS forum experts.