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.

CS_Hold doesn't work properly.

Other Parts Discussed in Thread: HALCOGEN, RM46L852

Hello,

I am having a problem with SPI in compatibility mode. The CS_HOLD bit isn't working properly in my configuration.

In order to keep the CS pin low during an N bits transmittion you need to write 1 to the CS_HOLD bit in SPIDAT1. And in the final transfer it must be set to 0 (zero) for it to rise again.

I am doing this but I can't see the CS pin going to 3v3 in my oscilloscope.

Here's my code:

	for (i = 0; i < SIZE; i++) {
		send((uint8_t *)addr++, i);
	}

Which in turn calls this:

 

uint32_t send(uint8_t *data, uint32_t bytesLeft) {
	uint32_t csHold = SPI1_config.hold;

	if (bytesLeft == 1) {
		csHold = 0;
	}

	SPI1_send_byte(data, csHold);
	return 1;
}

Which in turn calls this:

static void SPI1_send_byte(uint8_t *data, uint32_t csHold) {
	uint8_t spiBuf;
	uint32_t reg;

	while (!(SPI1Reg->SPIFLG & 0x200U));

	reg = *data | (SPI1_config.CS << 16) | (csHold << 28);
	SPI1Reg->SPIDAT1 = reg;
	spiBuf = SPI1Reg->SPIBUF;
}

And they use this structure:

static struct spi_config_data SPI1_config = {
	.baud_MHz = 1,
	.n_Bits   = 8,
	.CS       = 0xFE,
	.mode     = 1,
	.hold     = 1
};

As I saw in the code generated by HALcogen, it is doing exactly this. It sets the CS_HOLD bit in SPIDAT1 from the first transmission to the N-1. Clearing it to 0 in the last transaction.

  • Here's my configuration (I'm not using any interrupts for this)

    		SPIreg1->SPIGCR0 = 0x1U;	/*Sets the module out of reset*/
    
    		/** -Configure mode*/
    		SPIreg1->SPIGCR1 = ( spi_data.mode				/*Master mode enabled*/
    					   		| (spi_data.mode << 1U));	/*Clock mode: internal*/
    
    		SPIreg1->SPIDELAY = (38U << 24U);		/*C2TDelay = 500ns*/
    		
    		/** -Configure master mode*/
    		SPIreg1->SPIFMT0 = ( spi_data.n_Bits		/*Data Bits*/
    							| (prescale << 8U)		/*Speed*/
    							| (450U << 24U));		/*No parity bit is transmitted*/
    		SPIreg1->SPIFMT1 = ( spi_data.n_Bits		/*Same as SPIFMT0*/
    							| (prescale << 8U)		/*Same as SPIFMT0*/
    							| (450U << 24U));		/*Same as SPIFMT0*/
    		SPIreg1->SPIFMT2 = ( spi_data.n_Bits		/*Same as SPIFMT0*/
    							| (prescale << 8U)		/*Same as SPIFMT0*/
    							| (450U << 24U));		/*Same as SPIFMT0*/
    		SPIreg1->SPIFMT3 =	( spi_data.n_Bits		/*Same as SPIFMT0*/
    							| (prescale << 8U)		/*Same as SPIFMT0*/
    							| (450U << 24U));		/*Same as SPIFMT0*/
    		/** -Clear flags*/
    		SPIreg1->SPIFLG = 0xFFFFFFFFU;
    
    		/** -Configure input/output*/
    		SPIreg1->SPIPC1 = ( 1U			    /*CS...		1 -> output, 0-> input*/
    				   	   	   | (1U << 8)		/*ENA...	1 -> output, 0-> input*/
    				   	   	   | (1U << 9)		/*CLK...	1 -> output, 0-> input*/
    				   	   	   | (1U << 10)		/*SIMO...	1 -> output, 0-> input*/
    				   	   	   | (0U << 11));	/*SOMI...	1 -> output, 0-> input*/
    
    		/** -Configure open-drain*/
    		SPIreg1->SPIPC6 = ( 0U 			/*CS...		1 -> high impedance, 0-> output value on pin ins logic 1*/
    					   	   | (0U << 8)		/*ENA...	1 -> high impedance, 0-> output value on pin ins logic 1*/
    					   	   | (0U << 9)		/*CLK...	1 -> high impedance, 0-> output value on pin ins logic 1*/
    					   	   | (0U << 10)		/*SIMO...	1 -> high impedance, 0-> output value on pin ins logic 1*/
    					   	   | (0U << 11));	/*SOMI...	1 -> high impedance, 0-> output value on pin ins logic 1*/
    	
    		/** -Configure pull-up selection*/
    		SPIreg1->SPIPC8 = ( 1U				/*CS...		1 -> pull up on pin, 0-> pull down on pin*/
    					   	   | (1U << 8)		/*ENA...	1 -> pull up on pin, 0-> pull down on pin*/
    					   	   | (1U << 9)		/*CLK...	1 -> pull up on pin, 0-> pull down on pin*/
    					   	   | (1U << 10)		/*SIMO...	1 -> pull up on pin, 0-> pull down on pin*/
    					   	   | (1U << 11));	/*SOMI...	1 -> pull up on pin, 0-> pull down on pin*/
    
    		/** -Enable SPI pins to be used*/
    		SPIreg1->SPIPC0 = ( 1U        		/* SCS[0]*/
    					   	   | (1U << 8U)  	/* ENA */
    					   	   | (1U << 9U)  	/* CLK */
    					   	   | (1U << 10U)  	/* SIMO */
    					   	   | (1U << 11U)); 	/* SOMI */
    		
    		/** -Enable SPI module*/
    		SPIreg1->SPIGCR1 |= (1U << 24U);	/*Enable SPI*/							/*Enable SPI*/
    

  • Pablo,

    When I have this sort of trouble the first thing I check is whether I can set the pin as a GPIO, toggle it by writing to the pin control registers, and see the toggle on the oscilloscope.  I always do this just by opening CCS up,  starting the program (Go past your init code because some low level config on the device could be the problem, like pin muxing...) and then open the register view to change the mode of the pin to confirm that it does or doesn't toggle.

    So I'd suggest giving this a shot.  Also you can check whether the DIN register mirrors what you program into the DOUT register when you're doing this test.  If you see that DIN follows DOUT you can usually conclude that either you've got a problem with the scope probe (is it grounded to the right place?) or maybe the pin function can be on two different pins and you need to change the IO mux.

    I read your first post about CSHOLD usage and that looked right so I'm betting it's something simple.

     

  • Thank you very much for your reply. 

    I did many tests, but wasn't able to locate the problem. Usually I'm programming another part of the code when I find a weird bug in the low level drivers and after 8 hours looking at a screen with lots and lots of code, it gets really hard for me to locate these problems, especially since the amount of information available is enormous. 

    That's the first thing I'll try tomorrow morning, but I don't think it's anything wrong with the pinmux. When I don't use the CS_HOLD it works the way it's supposed to work. It stays low for the whole 8 bit transfer, but When I use the it, it doesn't work like it's supposed to. 

  • It worked. So .. any ideas what might be wrong?

  • Pablo,

    What value do you have in SPIDEF (offset 0x4C)?  This sets the values (High or Low) for the chip selects between transmissions.

    EDIT:  Also - have you confirmed that when you have 1 byte left, the value written into SPIDAT1 has a '0' in the CSHOLD bit?

    i.e. that the code that should be handling this case is actually executing... not being skipped due to some C code issue?

     

  • Sorry it took me so long to answer. I was in a meeting the entire afternoon.


    As you may know, from the code above, first I am writing the data, cs and cs_hold values in a variable before writing to SPIDAT1:

    reg = *data | (SPI1_config.CS << 16) | (csHold << 28); where SPI1_config.CS = 0xFEU

    Here are the values of what is wirtten to SPIDAT1 and what I see in SPIDEF:

    reg    ->   0x10FE0011
    spidef->   0x0000003F

    reg    ->   0x10FE007F
    spidef->   0x0000003F

    reg    ->   0x00FE004C
    spidef->   0x0000003F

  • Pablo,

    I don't see anything wrong in your code,  of course I could be missing it but nothing has struck me as wrong.

    I do see that you are setting up the ENA pin for use - are you talking to a slave device that uses the ENA handshake?  And, have you transmitted anything *more* than just the three words ... will a 4th word transfer if you try? 

    If you are not using the ENA pin then please configure it as GIO and not as SPI.  And if you are using it, please confirm that it is being deasserted at the end of the transmission by the slave that you are talking to.

    Otherwise, I would start checking the actual SPI registers if you haven't (if the above 'reg' was a CPU register value did it get to the right place in the SPI memory map?) and/or start looking at error flags to see if any are set.

     

  • Sorry it took me so long to answer. I was out sick yesterday and half the day today.

    I set ENA to GPIO. Nothing happened.

    I tried sending more words. Nothing happened.

    I don't use cs_hold bit everything works. I use the cs_hold bit CS doesn't respond. It starts @3V3, goes to 0V for about 500ns and then goes up to 3V3 again and then gos down to 0V and doesn't come out of it.

    Here's a sample of what I'm doing. Maybe you can see my error.

    2626.project.zip

  • I restarted my PC then it started working. Really really weird. But it works now.

  • Pablo,

    Here is a project using SPI1 to send 4 16bits data using CS0 in hold mode.
    This code is generated by Halcogen. You can use it as example.
    I'm using RM46L852, in this example.

    0410.SPI_CS_HOLD.zip

    Here is a screen shot of SYS_MAIN.c

    And here is the waveform on the scope.

    If you change in main the following statement:

    spitestcfg.CS_HOLD = 0;

    This is the result:

    Please, let me know if this is helpful.

  • Sorry I took such a long time to answer to your reply. I fixed the problem. For some unknow reason, everything started working again after I shutdown my PC and let it rest for a bit before turning it on again. 

    I usually don't turn off my PC, and for some reason after I restarted it, I could see everything working properly in my oscilloscope. I didn't have to change anything in my code. It's a little weird that restarting my PC worked, but I'm not complaining. 

    Thank you very much for your attention and your help