chipKIT® Development Platform

Inspired by Arduino™

PLEASE Help about eventSerial() UART interrupt on mpide

Created Sun, 21 Dec 2014 06:58:47 +0000 by devrirobotik


devrirobotik

Sun, 21 Dec 2014 06:58:47 +0000

Please help me. I am hopeless. How can I read the characters as they came via RX buffer? I mean exactly the same as serialEvent() on arduino. I mean the UART Interrupt.. I cant do it on mpide :( How? Please help me! I did these:

void setup() { Serial3.begin(9600); // U4 PC IFS0bits.U2RXIF =0; IEC0bits.U2RXIE =1; }

void loop() { some code.. ... printx and etc.. }

void attribute((interrupt)) _U2RXInterrupt(void) { IFS0bits.U2RXIF = 0;

x=Serial1.read(); ... etc }

But It does not work!.. :((( I could not do it for weeks.. Please help.... :(


majenko

Sun, 21 Dec 2014 10:24:45 +0000

There is so much wrong there I don't know where to begin...

Firstly, and most importantly, the built in serial system is already using the RX interrupt to fill the RX buffer as characters arrive. You can't use it as well. You certainly can't use it as well and still expect the internal serial system to also function.

Secondly, interrupt routines must usually be defined 'extern "C" {....}'.

Thirdly, the chipKIT platform has its own set of interrupt handlng and manipulating routines. It maintains its own internal vector table which is controlled by a set of special functions: setIntVector(), setIntPiority(), clearIntFlag(), setIntEnable(), etc.

The documentation for those functions is very poor at the moment - I must get around to writing a proper interrupts tutorial sometime - maybe over the christmas break.


devrirobotik

Sun, 21 Dec 2014 18:08:00 +0000

Thank you majenko for showing me what is wrong to do.

And I am sorry to question you but, why wouldn't you show me what is right to do when you have a knowledge about this subject?

I will be waiting for your replies, Thank you.


majenko

Sun, 21 Dec 2014 19:13:35 +0000

I will do when I get a chance. I'm somewhat busy at the moment.

The best fix would be an enhancement to HardwareSerial to allow the insertion of a routine into the existing ISR. That will take time and work on my part.

The other method would be to use 100% your own serial code.


devrirobotik

Sun, 21 Dec 2014 19:27:26 +0000

Ok majenko. I don't know anything about what to do.

I have made a code that works but it doesn't exit back to main loop after the first RX recieve, It just frosts. After some work, I realised that it does not clear the U2RXIF flag.

I came this far. So, I need your helps. So, I will be waiting for your helps.

Thank you so much..

(I can post the code here if needed.)


devrirobotik

Sun, 21 Dec 2014 19:32:23 +0000

It can't clear the U2RXIF because I did not use that extern "c" thing? Would that be the problem?


majenko

Sun, 21 Dec 2014 20:25:50 +0000

You have a conflict between ISRs. Your ISR is trying to read from the RX buffer. That RX buffer is filled by the HardwareSerial ISR. There can be only one ISR, so which is it? One filling the buffer, or one emptying the buffer? Who knows? Either way it will never work.

I have just experimented with adding interrupt callback support to the HardwareSerial code, and it so far seems to work well. When it's released you would be able to do this:

void setup() {
	Serial.begin(9600);
	Serial.attachInterrupt(receive);
}

void loop() {
}

void receive(int ch) {
	Serial.write(ch);
}

By attaching an interrupt it disables the normal buffering and instead passes the received character direct to your defined ISR function.

I'll look at getting it into the github repository for the next MPIDE release. I'm also going to put it in the chipKIT core of UECIDE.

First though I need to make it work right with USB CDC/ACM Serial. Gotta keep the two working the same...


majenko

Sun, 21 Dec 2014 20:44:51 +0000

Ok, that code is now in the normal chipKIT core for UECIDE (beta version only though) and ready for use. Just sorting out the MPIDE stuff now. It'll take some time (weeks?) before you can get at that version though, so best make the switch to UECIDE now :twisted:


devrirobotik

Sun, 21 Dec 2014 20:57:33 +0000

Hello majenko.

I have my own libraries of mpide and so much work in it (yes maybe mounths). One of them (was really hard for me) I did SoftwareSerial to work with ChangeNotification and make the buffer iterative. These special functions are much oftenly used in my mpide. So it is impossible for me for this project to change the IDE for now.

So can you please tell me where can I download that beta UECIDE hardware library?

Thank you so much for your helps!


majenko

Sun, 21 Dec 2014 21:01:41 +0000

What works in MPIDE should work in UECIDE without modification. After all, UECIDE started out as MPIDE originally anyway.

I can post the changed files here, but whether to post the UECIDE version, or the MPIDE Github version depends on which version of MPIDE you're running. The UECIDE version is pre-PIC32MZ merge, the MPIDE version is post PIC32MZ merge. If you're running a recent test version of MPIDE then you'll need the MPIDE version, otherwise the UECIDE one is what you need.

What version of MPIDE are you running?


devrirobotik

Sun, 21 Dec 2014 21:21:21 +0000

It is MPIDE-0023-windows-20130918-test (I had found it by digging some forums to find changenotification libraries.. )

And I m Using Cerebot MX7CK board type. But my board is not MX7CK It is just a naked-32MX795F512L..

So I have made several modifications like adding UART5 UART6 UART7 serial communications or some small changes etc..

So what code should I add to make a simple UART RX interrupt?


majenko

Sun, 21 Dec 2014 21:26:37 +0000

Ok, replacing the existing HardwareSerial.* files with these ones should work for you.


devrirobotik

Sun, 21 Dec 2014 21:48:50 +0000

Ok. Thank you really so much majenko. I will be trying your attachment. And I will tell you the feedback as I try it.

Thank you so much for your time. :) I will be back :)


devrirobotik

Sun, 21 Dec 2014 21:53:52 +0000

Oh.. By the way..

What code should I try in my main code?

I mean..

void setup() { serialinterruptsetup() // ??? what should be here? }

void loop() {}

void u2RXinterrupt() //what should be the name here?? { //what should i do here? }

I forgot to ask?

Thank you...


majenko

Sun, 21 Dec 2014 21:55:08 +0000

I posted the sample code above. Attach a function as an interrupt, and that function gets called with the incoming character. Do what you want with it. Just don't take too long with it ;)


devrirobotik

Sun, 21 Dec 2014 22:23:10 +0000

Hey.

I know I make you have trouble with me so much. But here is the answer of the compiler:

sketch_dec22a.cpp: In function 'void setup()': sketch_dec22a.cpp:6:4: error: 'Serial' was not declared in this scope sketch_dec22a.cpp: In function 'void receive(int)': sketch_dec22a.cpp:14:4: error: 'Serial' was not declared in this scope

:(

for the code:

void setup() { Serial.begin(9600); Serial.attachInterrupt(receive); }

void loop() { }

void receive(int ch) { Serial.write(ch); }

What should be wrong with it?

Thank you..


devrirobotik

Sun, 21 Dec 2014 22:29:58 +0000

No no no.. My mistake sorry. Wrong alert. Please do not take care of the last message.. I couldnt copy the files. Sorry.. It is my mistake..

You take care of me so much. I am so happy now.

Thank you for all your efforts.

By the way, I am the head manager of some re&de company. And we have some projects. I hope we will work together on some projects soon. I will be glad to communicate with you soon.

Thank you for all you have done this far :)

Have a nice day :)) And really thank you so much!!! :))


majenko

Sun, 21 Dec 2014 22:35:01 +0000

Glad to be of service.

Still, I suggest you take a look at UECIDE - hopefully one day it'll be replacing MPIDE...


devrirobotik

Wed, 24 Dec 2014 21:32:59 +0000

Ok.. I will be using it for all my new projects I hope, if it supports ARMs too.

Majenko I did this:

void HardwareSerial::doSerialInt(void)
{
   uint16_t      bufIndex;
   uint8_t   ch;
   //uint32_t tmp_mode;

   /* If it's a receive interrupt, get the character and store
   ** it in the receive buffer.
   */
   if ((ifs->reg & bit_rx) != 0)
   {
      // while bytes available
      while(uart->uxSta.reg & 0x01)
      { 
         // error check
         if(uart->uxSta.reg & 0x04) // checking FERR 0x04
         {
            ch = uart->uxRx.reg; // dispose of byte
			//purge();
         }
         else if(uart->uxSta.reg & 0x02) // checking OERR 0x02
         {
            // clear OERR bit
            uart->uxSta.clr = 0x02;
			//purge();
         }
         else
         {
            ch = uart->uxRx.reg;
            bufIndex   = (rx_buffer.head + 1) % RX_BUFFER_SIZE;
         
            /* If we should be storing the received character into the location
            ** just before the tail (meaning that the head would advance to the
            ** current location of the tail), we're about to overflow the buffer
            ** and so we don't write the character or advance the head.
            */
			if (rxIntr != NULL) 
			{
				rx_buffer.tail	= (rx_buffer.tail + 1) % RX_BUFFER_SIZE;
				rxIntr(ch);
			} 
			if (bufIndex != rx_buffer.tail)
			{
				rx_buffer.buffer[rx_buffer.head] = ch;
				rx_buffer.head = bufIndex;
				//purge();
			}
			//delay(5);
		
         } // if error check
      } // while

      /* Clear the interrupt flag.
      */
      ifs->clr = bit_rx;
   }

I have modified the code you have sent with this one because it sometimes miss some characters and some problems occur that I don't remember now. One of them is, microcontroller is frozing after a while. I analyse the reason and I came up with, when loop time exceeds the serial flow period it frosts.

I mean, My module is giving me 102 characters in every 200ms. When my main loop exceeds 200ms, the microcontroller frosts after 3 or 5 seconds. So, I think the buffer become full so microcontroller stops.

And with this code, I still couldn't solve that problem. It still frosts if the main loop time exceeds the modules period.

How can I solve this problem do you have any idea? Would you help me about it?

Thank you.


devrirobotik

Wed, 24 Dec 2014 21:35:23 +0000

Here is an easy to read version:

void HardwareSerial::doSerialInt(void)
{
   uint16_t      bufIndex;
   uint8_t   ch;

   if ((ifs->reg & bit_rx) != 0)
   {
      // while bytes available
      while(uart->uxSta.reg & 0x01)
      { 
         // error check
         if(uart->uxSta.reg & 0x04) // checking FERR 0x04
         {
            ch = uart->uxRx.reg;
         }
         else if(uart->uxSta.reg & 0x02) // checking OERR 0x02
         {
            // clear OERR bit
            uart->uxSta.clr = 0x02;
         }
         else
         {
            ch = uart->uxRx.reg;
            bufIndex   = (rx_buffer.head + 1) % RX_BUFFER_SIZE;

			if (rxIntr != NULL) 
			{
				rx_buffer.tail	= (rx_buffer.tail + 1) % RX_BUFFER_SIZE;
				rxIntr(ch);
			} 
			if (bufIndex != rx_buffer.tail)
			{
				rx_buffer.buffer[rx_buffer.head] = ch;
				rx_buffer.head = bufIndex;
			}
		
         }
      } 
      ifs->clr = bit_rx;
   }

majenko

Wed, 24 Dec 2014 22:07:18 +0000

That's the general problem of using interrupts. You have to handle them fast enough or you get problems. Not alot you can do about that, besides move most of your processing out of the interrupt - and then you get a system that is almost the same as the existing ringbuffer arrangement anyway.

I would suggest actually trying to come up with a way of doing what you're trying to do without using the interrupts. What exactly is it you're trying to achieve at the moment?


devrirobotik

Thu, 25 Dec 2014 19:39:56 +0000

Time is important for me because I am working on some accelerometer so time shift is important for me. So I was in need of interrupts. But if you say so, I think I should use parsing the string outside the interrupt function.

Thanks for your helps so much :).. By the way I have came up with a weird problem..

It is a really weird problem. I am using Serial Port 4. I mean U5. (I activated it on libraries.)

And my code is the simplest MultiSerial code. (Serial4->Serial and Serial->Serial4)

void setup() {
  // initialize both serial ports:
  Serial.begin(9600);
  Serial1.begin(9600);
}

void loop() {
  // read from port 1, send to port 0:
  if (Serial4.available()) {
    int inByte = Serial4.read();
    Serial.write(inByte); 
  } if (Serial.available()) {
    int inByte = Serial.read();
    Serial4.write(inByte); 
  }
}

And my library is the simple library (that without the interrupt function.)

And sometimes It works properly.

But many times It gives different characters.

(By the way I used all the baudrates and It is definitely not a Serial.Write problem. I am positive it is a Serial.read problem)

For example:

$VNINS,$VNINS,$VNINS...

or

$VNIdgsgsglgkchnlskfjg(weird charactes)VNIdgsdfgdf$VNalgfkdsjg

or

$VNINS,0035(null)(null)(null)(null)(null)(null) (I mean it gives 0xFFs.. )

and so on....

but It should give: $VNINS,,333811.902862,1694,0004,+009.500,-004.754,-000.225,+32.95602815,- 096.71424297,+00171.195,-000.840,-000.396,-000.109,07.8,01.6,0.23*5F

I really dont understand the problem. :S:S

I checked the input and output pins with some logic analyzer many times and there's nothing wrong on hardware side.

I don't know what should I do :S

Thank you so much for your helps..