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.

Problem sending and receiving with SCI

Other Parts Discussed in Thread: RM48L952, HALCOGEN

Hello, I am using two RM48L952 Hercules microcontrollers.

WHAT HAPPENED

I need to exchange data using the SCI (using the SCI module and NOT the LIN module in SCI mode). The communication can happen anywhere, so the second microcontroller can't wait forever for the communication.

I wrote the init, send, receive and hasData functions. I can see in the oscilloscope the microcontroller sending data without any problems. When I use the hasData function to check if any data was received I can see that the flag was not set, but when I put a breakpoint  in the code and check the registers I can see that the data has been received correctly but it hasn't set the flag.

I didn't pay it any attention and simply removed the hasData function and started receiving the data by using the read function. I saw that I received the correct data and then keep on going. At that moment both microcontrollers get stuck in a send function. Apparently after doing this, reading the byte by force the tx and rx flags never get set anymore and then they get stuck forever waiting for the tx ready bit to be set or the rx bit, when I put the hasData function in.

Here's my code:

/*SCI FUNCTIONS*/


void init(void) {
	SCIReg->SCIGCR0 = 0U;
	/*Get the module out of reset*/
	SCIReg->SCIGCR0 |= 1U;
	/*Clear interrupts*/
	SCIReg->SCICLEARINT = 0xFFFFFFFFU;
	SCIReg->SCICLEARINTLVL = 0xFFFFFFFFU;
	/*Configure Global Control Register*/
	SCIReg->SCIGCR1 = 	((1 << 1)  | /*Asynchronous mode*/
						(1 << 5)   | /*Use internal clock*/
						(1 << 4)   |
						(1 << 24)  | /*Enable RX*/
						(1 << 25));  /*Enable TX*/
	SCIReg->BRS = (53 | (4 << 24)); 
	
	SCIReg->SCIFORMAT = 7; 

	SCIReg->SCIPIO0 = (1 << 1) | /*RX pin is SCI RX*/
					  (1 << 2);  /*TX pin is SCITX*/
	SCIReg->SCIPIO1 = (0 << 2);  /*RX pin is SCI RX*/ /*TODO: verificar linha*/

	SCIReg->SCIPIO8 = (1 << 1) |
					  (1 << 2);  /**/

	SCIReg->SCIGCR1 |= (1U << 7);
}

void send(const uint8_t *data, uint32_t size) {
	uint32_t i;

	for(i = 0; i < size; i++) {
		while((SCIReg->SCIFLR & SCI_TXMASK) == 0) {}
		uint8_t test = *data++;
		SCIReg->SCITD = test;
	}
}

void receive(uint8_t *buf) {
	while((SCIReg->SCIFLR & SCI_RXMASK) == 0) {}
	*buf++ = (uint8_t)SCIReg->SCIRD;
}

void receiveByte(uint8_t *byte) {
	*byte = (uint8_t)SCIReg->SCIRD;
}


bool hasData(void) {
	bool f = (SCIReg->SCIFLR & SCI_RXMASK != 0);
	if(f != false) {
		SCIReg->SCIFLR |= SCI_RXMASK;
	}

	return f;
}


/*MY USAGE OF THE FCUNTIONS first hercules*/
uint8_t firstByte = 50;
uint8_t received[12];

send(&firstByte, 1);

if(hasData())
    receiveByte(&received[0]);

send("myString",9);



/*MY USAGE OF THE FCUNTIONS second hercules*/
uint8_t received[12];

if (hasData()) {
    receiveByte(&received[0]);

    if(received[0] != expected) return;
   
    send("otherString", 12);
}

The code above is a very simplified usage of my code, but it still fails. Literally the flags are not signalling the module, which may mean that there's something wrong with my code, but I verified it against HALcogen and I can't see a problem.

By the way, DMA is out of the question as well as receiving by interrupt.

MY INTENTIONS

From what I understand this module is double-buffered meaning that it can store 2 bytes in the TX and RX buffers (am I right?) before being overrun. This checks out in the code because it can send and receive the byte in the register 2 times before halting (both channels literally send 2 times before halting in the send function).

As I can't guarantee that both micorcontrollers will be at the same time at the same place in order to send and receive  the buffer and the microcontroller's internal buffer consists of only 2 bytes, I intended to send one byte to synchronize both channels (micro1 sends a byte and waits for a response) so that it can send the rest of the buffer as well as receive a buffer from micro2

  • Hi Pablo,

    It looks like your send routine will get stuck in a busy loop until all the bytes in the string are transmitted. During that time the bytes received will get overwritten.

    What you need is a TX and RX Queue of your own. 

    In your super loop:

    1. Check TX empty condition and send next byte from your TX Q.
    2. Check RX ready condition and push the received byte into your RX Q.
    3. Inspect your RX Q for message patterns, or any startup condition and push new messages to TX into TX Q.

    Repeat 1:3 for ever.

    Avoid busy waits.

    DMA and or interrupts will be easier!

    Good luck,

    Joe

  • Ok, 

    1 - I think I'm already doing that ... while((SCIReg->SCIFLR & SCI_TXMASK) == 0) {}

    2 - I'm already doing that. The receive function has while((SCIReg->SCIFLR & SCI_RXMASK) == 0) {} and the receiveByte function is called only after the hasData function. You can see the hasData function in my post. The hasData is a little different than those infinite loops because the second micro cannot get stuck forever waiting for a byte to receive. I always check before sending a byte and I noticed that the code gets stuck in an infinite loop waiting for the TX ready bit to get set in the line specified in 1. There's something else wrong, this is not the problem apparently. 

    3 - If I'm not mistaken I'm also doing that. 

     

    PS: I can't use DMA because I am using MibSPI5 in SPI mode receiving data via DMA, and the Spi5Rx and SciRx share the same request line (reqline 30) and I can't use interrupts because of other reasons. 

     

    So .. any ideas?

  • "1 - I think I'm already doing that ... while((SCIReg->SCIFLR & SCI_TXMASK) == 0) {}"

    NO. You are stuck in this while loop until ready to TX. At the same time you could be missing the bytes received.
    What you need is a construct like if (SCIReg->SCIFLR & SCI_TXMASK) SCIReg->SCITD = TXQ[outIdx++]; kind of like your hasData()
  • This code is almost the same as in HALcogen, I simply removed the possibility to send via DMA.

    I verified both flags in one of my tests and I can see that neither the Rx flag nor the Tx flag are set.

    I can see in the oscilloscope that it has sent a byte, I see that byte in the SCIRD register in the other channel BUT the flag hasn't been set.

    After a while (2 or 3 sends) the Tx flag stops being set and stays like that until I reset it.

    I tried using your suggestion and the same thing happened.

  • I wired up my board a little bit more and put both channels in the oscilloscope.

    I noticed that the second channel, after it gets stuck without setting the Tx bit, it just keeps on sending the same byte forever. This means that the SCI module is actually sending the byte in the buffer, but it never signals that it has stopped sending ...
  • Pablo,

    You should avoid "SCIReg->SCIFLR |= SCI_RXMASK;" from your hasData() routine. That will clear all write to clear flags unintentionally. RX_RDY flag will be cleared when you read RD register, no need to explicitly clear that bit. If for some reason you want to clear some bits in the FLR register write 1s to the flags you want to clear. Writing 0s will not clear "other" bits.

    SCIReg->SCIFLR = (RX_RDY | RX_OV | …);

    For an experiment, can you send just one byte in response to a byte received and test your ping-pong routine, instead of sending the multi-byte response on both micros?

    Joe

  • Soooooooo .... .

    I found the problem. I rebuildt the project and the same thing happened and it didn't make sense. I then deleted the generated files and folders that are created after compilation and the rebuilt the project ... it started working ...


    This seems to be a CCS bug? Maybe some part of some file wasn't being compiled correctly?

  • So your original code works without any modifications! Interesting ... must be a CCS bug :-)

  • Yep. 

    Something like that has already happened once or twice. The strange thing is that a rebuild isn't enough, neither a clean and then rebuild. 

    You literally have to delete the generated folders and files that are generated during compilation time. Looks like a CCS bug, but it could be a problem with my installation. I used to have CCS 5.5, installed over it and then removed 5.5 manually because it wasn't being removed. Unfortunately I don't know how to reproduce it :(

    But thank you very much for your help