Bits Are Scrambled - embedded
The Problem: I send one value into a UART and nulls emerge on the other UART.
--- Details ---
These are both PIC processors (PIC24 and PIC32)
They are both hard wired onto a printed circuit board.
They are communicating, each via one of the UART modules which reside within them.
They are (ostensibly; according to docs) both configured for 115200 bps, 8-N-1
No handshaking, no CTS enabled, no RTS enabled; I'm just putting bytes on the wire and out they go.
(These are short little 4-byte commands and responses which fits pretty neatly)
The PIC32 is going 80 MHz.
The PIC24 has F[cy] = 14745600
i.e., it is going 14.7456 MHz
The PIC24 sends four bytes (a specific command sequence)
When I set a breakpoint at the Interrupt Service Routine for the UART, The PIC32 shows nulls, then I am seeing repeated hits on the (PIC32 code) breakpoint after the first four, and I continue to see nulls (which makes sense since the PIC24 is not sending anything)
i.e., the UART appears to be repeatedly generating interrupts when there is no reason
I did not write the code on the PIC32 side, and I am learning daily how it works.
Then I let the code just run, and I inevitably wind up on a line that says
52570 1D01_335C 9D01_335C _general_execption_handler sdbbp 0x0
When I get there,
The cause register holds 0080181C
The EPC register holds 9D00F228
The SP register holds 9F8FFFA0
This happened like clockwork, so I got suspicious of the __ISR that would not stop. MpLab showed me this...
432:
433: //*********************************************************//
434: void __ISR(_UART1_VECTOR, ipl5) IntUart1Handler(void) //MCU communication port
435: {
9D00F204 415DE800 rdpgpr sp,sp
9D00F208 401A7000 mfc0 k0,EPC
9D00F20C 401B6000 mfc0 k1,Status
9D00F210 27BDFF88 addiu sp,sp,-120
9D00F214 AFBA0074 sw k0,116(sp)
9D00F218 AFBB0070 sw k1,112(sp)
9D00F21C 7C1B7844 ins k1,zero,1,15
9D00F220 377B1400 ori k1,k1,0x1400
9D00F224 409B6000 mtc0 k1,Status
9D00F228 AFBF0064 sw ra,100(sp) ;<<<-------EPC register always points here
9D00F22C AFBE0060 sw s8,96(sp)
9D00F230 AFB9005C sw t9,92(sp)
9D00F234 AFB80058 sw t8,88(sp)
9D00F238 AFAF0054 sw t7,84(sp)
9D00F23C AFAE0050 sw t6,80(sp)
9D00F240 AFAD004C sw t5,76(sp)
9D00F244 AFAC0048 sw t4,72(sp)
9D00F248 AFAB0044 sw t3,68(sp)
9D00F24C AFAA0040 sw t2,64(sp)
9D00F250 AFA9003C sw t1,60(sp)
9D00F254 AFA80038 sw t0,56(sp)
9D00F258 AFA70034 sw a3,52(sp)
9D00F25C AFA60030 sw a2,48(sp)
9D00F260 AFA5002C sw a1,44(sp)
9D00F264 AFA40028 sw a0,40(sp)
9D00F268 AFA30024 sw v1,36(sp)
9D00F26C AFA20020 sw v0,32(sp)
9D00F270 AFA1001C sw at,28(sp)
9D00F274 00001012 mflo v0
9D00F278 AFA2006C sw v0,108(sp)
9D00F27C 00001810 mfhi v1
9D00F280 AFA30068 sw v1,104(sp)
9D00F284 03A0F021 addu s8,sp,zero
I look a little more closely at the numbers, and I see that at that time, if we add 100 (0x64) to FFA0 (the bottom 16 bits of the SP) we get 0x10004, which I am guessing is 4 too much.
PIC Manual DS61143E-page 50 says that that nomenclature means, SW Store Word Mem[Rs+offset> = Rt and other experts have told me that the cause register is telling me that the EXCCODE bits are 7 which is the code for a bus exception on load or store.
Or, I'm totally guessing here (would love to get some experts' knowledge on this) something is not clearing something and I'm encountering infinite recursion on an int handler.
All of this is starting to make sense.
THE QUESTION
Could someone please suggest the most common reasons for an int like this to be repeatedly hitting me ?
Does anyone see any common relationship between the bogus nuls coming from the UART which could somehow be connected with this endlessly generated int ? Am I even on the right track ?
In your answer, please tell me how to acknowledge the Int from the UART. I know how I do that in the PIC24 (I wrote that code totally, in ASM) but I don't know how this is done in in C on the PIC32. Assembly will be fine. I'll inline it. I'm working with code I didn't write here, and I thank you for your answers
What is the most common reason that the UART (#1, in this case) would be repeatedly generating interrupts ?
The most common reason an interrupt subroutine is called over and over is that the interrupt request is never acknowledged in the routine.
Are you sure you clear the corresponding IRQ bit?
To ease UART debugging you should first connect the UART to a PC and make sure your target can communicate both ways with the PC. With two targets at the same time, you can't determine on which one the problem is apart from inspecting signals with a scope.
On many devices an interrupt must be explicitly cleared to prevent the ISR from simply re-entering when complete.
In most cases a UART will have status bits that indicate the source of the interrupt, knowing that might tell you something, but not telling us makes it difficult to help you. You can inspect the UART registers directly in the debugger, however in some devices the act of reading a bit may in fact clear a bit, and that is true in the debugger too, so be aware of that possibility (check the data sheet/user manual).
Some UARTS require their transmitter to be explicitly switched off to stop transmitting nulls, while others are triggered automatically when data is placed in the tx register and stop after the necessary number of bits are shifted out. Again check the data sheet/manual for the part. If the PIC32 code is known to be working, then since this possible error would be with the PIC24 code, it seems to fit. You can check this simply by using an oscilloscope on the Tx line from the PIC24, if it is transmitting, you will see at least start/stop bit transitions (framing). If there is nothing, then the problem is probably at the PIC32 end.
While you have the scope out, you can check that the bit timing is correct and that you are actually transmitting at 115200. It is easy to get the clocking wrong, and that should be your first check. If the baud rate is incorrect, the PIC32 will likely generate framing error interrupts, which if not handled may persist indefinitely.
Another possibility is that after transmission the PIC24 leaves the line in the "break" state, and that the PIC32 UART is generating "line-break" interrupts. That is why it is important to look at the UART status registers to determine the interrupt cause.
As you can see, there are many possibilities; I think I have covered the most likely ones, but more methodical debugging effort and information gathering on your part is required. I hope I have guided you in this too.
There were the three root causes which were in place...
The interrupt priority level was set at value 6 in the initialization code for UART1
The first line of the interrupt service routine was coded with an interrupt priority level of 5
The first three bytes of UART data were disappearing from the data stream (this is still unsolved)
Here's the not-so-obvious way they were causing the problem
First three bytes never appeared
Fourth byte did appear
Interrupt hit (as level 6) and invoked __ISR routine
__ISR was acting as ipl5 agent
First instruction executed (possibly more, I couldn't debug that accurately)
As soon as the first instruction finished, the "higher" priority 6 interrupt immediately kicked in
This resulted in the same interrupt again
The process repeated itself infinitely.
In short order, Stack Overflow resulted
The Fix
Make sure these two lines of code agree with each other...
The IPL line in the init code, wrong way then the right way
//IPC6bits.U1IP=6; //// Wrong !!! Uart 1 IPL should not be 6 !!!
IPC6bits.U1IP=5; //// Uart 1 IPL = 5 Correct way; matches __ISR
Interrupt Service Routine
void __ISR(_UART1_VECTOR, ipl5) IntUart1Handler(void) //// Operating as IPL 5
:
:
:
:
Poor design decision. If both are on same board SPI would have been more feasible and a lot faster.
Related
Why is TIM1 PWM Generation CH1 triggering input compare on TIM3
I'm very new to embedded SW development and I'm trying to understand as much as possible by realizing simple code for a STM32G031C6T6 MCU, so probabily this is a stupid question but I can't find the answer anywere. First I set up channel 1 of TIM1 for PWM generation, that is output on the PA8 pin and it's working properly. Then I set channel 1 of TIM3 for input capture, that is performed on the PA6 pin rising edge. In the code I started the timers with HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1) and HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_1). I run the the program and the input compare in TIM3 is triggered everytime there's a rising edge of the PWM signal generated by TIM1. I can't figure out why this is happening and I'm unable to find any info about this behavior. Last but not least I am sure that there's no physical connection between PA8 and PA6, plus the input compare channel is filtered (I tried to set the filter even at its max value) so that no noise from the PWM channel can trigger it. screenshot of the configuration in cubeMx [TIM3]: https://i.stack.imgur.com/ehXbe.jpg [TIM1]: https://i.stack.imgur.com/s95kU.jpg PS: after further testing i noticed that it happens only if I enable the input compare on channel 1 the other 3 channels seems to work just fine
LPC1225 UART Tx works, but Rx does not
My setup is: LPC1225FBD48/321 ext crystal: 16MHZ PLL: MSEL=6, PSEL=2 UART0: CLKDIV=250 DL=1 DIVADDVAL=1 MULVAL=4 PLL gives mainclk=96MHz ; PCLK for UART is: 96MHz/250=384kHz ; Bit rate: 384kHz/(16x1x1.25)=19200 And it works, but only when LPC transmits. When LPC receives a character, it reports 2 characters received and sometimes framing error. Similar problem for other bit rates. At lower rates, like 2400, LPC reports single character received and sometimes framing error, but received character is not the same as I sent. It looks like Tx and Rx are using different clocks. The UART works well when using bootloader with Flash Magic. Has anyone encountered such a problem?
I finally found a solution. After setting CLKDIV = 50 and DL = 5, the UART became fully functional. While the documentation did not prohibit the previous set of parameters and both sets should give the same result, only the latter allows two-way communication.
How to write ISR macro for 2 pins on the same port in PIC32MZ2048ECH144 using Microchip Harmony Configurator(MHC)?
I am using PIC32MZ2048ECH144. I have two switches connected to RH8(pin Number 81) and RH9(pin Number 82). I do not see any option in MHC to set interrupt at pin level, therefore I get the ISR generated for the port-H. I need the ISRs for each pin to be invoked separately. Hence, in "system_init.c", in "SYS_Initialize" function I added the following lines, PLIB_PORTS_PinChangeNoticePerPortEnable(PORTS_ID_0, PORT_CHANNEL_H, PORTS_BIT_POS_8); PLIB_PORTS_PinChangeNoticePerPortEnable(PORTS_ID_0, PORT_CHANNEL_H, PORTS_BIT_POS_9); The ISR generated by MHC in "system_interrupt.c": void __ISR(_CHANGE_NOTICE_H_VECTOR, ipl3AUTO) _IntHandlerChangeNotification_PortH1(void) { PLIB_INT_SourceFlagClear(INT_ID_0,INT_SOURCE_CHANGE_NOTICE_H); APP_SwitchChangeNoticed(); } I replaced the above ISR macro with the below lines: void __ISR(_ADC1_DATA22_VECTOR, ipl3AUTO) _IntHandlerChangeNotification_PortH1(void) { PLIB_INT_SourceFlagClear(INT_ID_0, INT_SOURCE_CHANGE_NOTICE); APP_SwitchChangeNoticed(); } void __ISR(_ADC1_DATA23_VECTOR, ipl3AUTO) _IntHandlerChangeNotification_PortH(void) { PLIB_INT_SourceFlagClear(INT_ID_0,INT_SOURCE_CHANGE_NOTICE_H); test1(); } This did not work out. I referred the link http://microchip.wikidot.com/faq:78. I feel I am wrong in choosing the vector numbers for the ISR macros from "/pic32mx/include/proc/p32mz2048ech144.h". (I used _ADC1_DATA22_VECTOR and _ADC1_DATA23_VECTOR thinking that the values against them 81 and 82 are pin numbers, which again did not work.) Any help or hints on how to set pin level interrupts(2 pins on the same port) would be really great! Kindly apologize for any mistakes in my post. Thanks in advance.
The short answer is that what you are asking for cant be achieved directly with two separate ISRs. There is only one change notification ISR vector available for the whole H port. You would normally achieve what you are looking for with an added software check to determine which of your two pins is in a different state. Another method is to simple move your signal to another port (if your board is not finalized). The name you give the function has no bearing on what the ISR will react to. The real magic comes in the __ISR macro arguments. For example: void __ISR(_CHANGE_NOTICE_H_VECTOR, ipl3AUTO) _IntHandler1234() Notice the _CHANGE_NOTICE_H_VECTOR; it signifies that this interrupt service routine will be called when the change notification interrupt happens on port H.
lpc1788 ssp (SPI) - proc to proc communication
I would like to send string of chars from one proc (master) to another (slave) and then read string from a slave. Currently im mixing up the arduino and LPC1788, using lpc as master and arduino as slave. LPC sent's the string correctly which is received by the arduino in ISR. In loop function i check if all of the chars are received and then try to send string back. On LPC side ISR is not working for some reason. I have set SR as SR = (1<<TNF) | (1<<RNE); So i have put delay after sending the string from LPC and then initiate read from arduino. What i see on LA for sending the string is: but reading of string from Arduino looks odd (string should be "Pong\n", it is not always P that i received... it varies) i guess majority of problem is within the sync of sending and reading of SPI buffer. How do i achieve that without functional ISR on LPC?
The SPI specification states that the CS (SSEL) line should be active during a frame and become inactive in between. NXP interpreted this as a word being one frame. This means that the CS as generated by the SSP block (the same goes for the legacy SPI) is only active during one transaction of up to 16 bits. Note also that there is always a gap in between the words/frames being sent. So even when you fill the FIFO or use DMA you will see 16 clock pulses, a short delay and then 16 more pulses. When using a GPIO pin as SSEL, please note you have to wait for SSEL assertion or de-assertion until the peripheral is idle.
Event handling in embedded code
I want to know how events are used in embedded system code. Main intention is to know how exactly event flags are set/reset in code. and how to identify which task is using which event flag and which bits of the flag are getting set/reset by each task. Please put your suggestion or comments about it. Thanks in advance. (edit 1: copied from clarification in answer below) Sorry for not specifying the details required. Actually I am interested in the analysis of any application written in C language using vxworks/Itron/OSEK OS. For example there is eventLib library in vxworks to support event handling. I want to know that how one can make use of such system routines to handle events in task. What is event flag(is it global/local...or what ?), how to set bits of any event flag and which can be the possible relationship between task and event flags ?? How task can wait for multiple events in AND and OR mode ?? I came across one example in which the scenario given below looks dangerous, but why ?? Scenarios is ==> *[Task1 : Set(e1), Task2 : Wait(e1) and Set(e2), Task3 : Wait(e2) ]* I know that multiple event flags waited by one task or circular dependency between multiple tasks(deadlock) are dangerous cases in task-event relationship, but how above scenario is dangerous, I am not getting it....Kindly explain. (Are there any more such scenarios possible in task-event handling which should be reviewed in code ?? ) I hope above information is sufficient ....
Many embedded systems use Interrupt Service Routines (ISR) to handle events. You would define an ISR for a given "flag" and reset that flag after you handle the event. For instance say you have a device performing Analog to Digital Conversions (ADC). On the device you could have an ISR that fires each time the ADC completes a conversion and then handle it within the ISR or notify some other task that the data is available (if you want to send it across some communications protocol). After you complete that you would reset the ADC flag so that it can fire again at it's next conversion. Usually there are a set of ISRs defined in the devices manual. Sometimes they provide general purpose flags that you could also handle as you wish. Each time resetting the flag that caused the routine to fire.
The eventLib in VxWorks is similar to signal() in unix -- it can indicate to a different thread that something occurred. If you need to pass data with the event, you may want to use Message Queues instead. The events are "global" between the sender and receiver. Since each sender indicates which task the event is intended for, there can be multiple event masks in the system with each sender/receiver pair having their own interpretation. A basic example: #define EVENT1 0x00000001 #define EVENT2 0x00000002 #define EVENT3 0x00000004 ... #define EVENT_EXIT 0x80000000 /* Spawn the event handler task (event receiver) */ rcvTaskId = taskSpawn("tRcv",priority,0,stackSize,handleEvents,0,0,0,0,0,0,0,0,0,0); ... /* Receive thread: Loop to receive events */ STATUS handleEvents(void) { UINT32 rcvEventMask = 0xFFFFFFFF; while(1) { UINT32 events = 0; if (eventReceive(rcvEventMask. EVENTS_WAIT_ANY, WAIT_FOREVER, &events) == OK) { /* Process events */ if (events & EVENT1) handleEvent1(); if (events & EVENT2) handleEvent2(); ... if (events & EVENT_EXIT) break; } } return OK; } The event sender is typically a hardware driver (BSP) or another thread. When a desired action occurs, the driver builds a mask of all pertinent events and sends them to the receiver task. The sender needs to obtain the taskID of the receiver. The taskID can be a global, int RcvTaskID = ERROR; ... eventSend(RcvTaskID, eventMask); it can be registered with the driver/sender task by the receiver, static int RcvTaskID = ERROR; void DRIVER_setRcvTaskID(int rcvTaskID) { RcvTaskID = rcvTaskID; } ... eventSend(RcvTaskID, eventMask); or the driver/sender task can call a receiver API method to send the event (wrapper). static int RcvTaskID; void RECV_sendEvents(UINT32 eventMask) { eventSend(RcvTaskID, eventMask); }
This question needs to provide more context. Embedded systems can be created using a wide range of languages, operating systems (including no operating system), frameworks etc. There is nothing universal about how events are created and handled in an embedded system, just as there is nothing universal about how events are created and handled in computing in general.
If you're asking how to set, clear, and check the various bits that represent events, this example may help. The basic strategy is to declare a (usually global) variable and use one bit to represent each condition. unsigned char bit_flags = 0; Now we can assign events to the bits: #define TIMER_EXPIRED 0x01 // 0000 0001 #define DATA_READY 0x02 // 0000 0010 #define BUFFER_OVERFLOW 0x04 // 0000 0100 And we can set, clear, and check bits with bitwise operators: // Bitwise OR: bit_flags | 00000001 sets the first bit. bit_flags |= TIMER_EXPIRED; // Set TIMER_EXPIRED bit. // Bitwise AND w/complement clears bits: flags & 11111101 clears the 2nd bit. bit_flags &= ~DATA_READY; // Clear DATA_READY bit. // Bitwise AND tests a bit. The result is BUFFER_OVERFLOW // if the bit is set, 0 if the bit is clear. had_ovflow = bit_flags & BUFFER_OVERFLOW; We can also set or clear combinations of bits: // Set DATA_READY and BUFFER_OVERFLOW bits. bit_flags |= (DATA_READY | BUFFER_OVERFLOW); You'll often see these operations implemented as macros: #define SET_BITS(bits, data) data |= (bits) #define CLEAR_BITS(bits, data) data &= ~(bits) #define CHECK_BITS(bits, data) (data & (bits)) Also, a note about interrupts and interrupt service routines: they need to run fast, so a typical ISR will simply set a flag, increment a counter, or copy some data and exit immediately. Then you can check the flag and attend to the event at your leisure. You probably do not want to undertake lengthy or error-prone activities in your ISR. Hope that's helpful!
Sorry for not specifying the details required. Actually I am interested in the analysis of any application written in C language using vxworks/Itron/OSEK OS. For example there is eventLib library in vxworks to support event handling. I want to know that how one can make use of such system routines to handle events in task. What is event flag(is it global/local...or what ?), how to set bits of any event flag and which can be the possible relationship between task and event flags ?? I hope above information is sufficient ....
If you're interested in using event-driven programming at the embedded level you should really look into QP. It's an excellent lightweight framework and if you get the book "Practical UML Statecharts in C/C++" by Miro Samek you find everything from how to handle system events in an embedded linux kernel (ISR's etc) to handling and creating them in a build with QP as your environment. (Here is a link to an example event).
In one family of embedded systems I designed (for a PIC18Fxx micro with ~128KB flash and 3.5KB RAM), I wrote a library to handle up to 16 timers with 1/16-second resolution (measured by a 16Hz pulse input to the CPU). The code is set up to determine whether any timer is in the Expired state or any dedicated wakeup pin is signaling, and if not, sleep until the next timer would expire or a wakeup input changes state. Quite a handy bit of code, though I should in retrospect probably have designed it to work with multiple groups of eight timers rather than one set of 16. A key aspect of my timing routines which I have found to be useful is that they mostly aren't driven by interrupts; instead I have a 'poll when convenient' routine which updates the timers off a 16Hz counter. While it sometimes feels odd to have timers which aren't run via interrupt, doing things that way avoids the need to worry about interrupts happening at odd times. If the action controlled by a timer wouldn't be able to happen within an interrupt (due to stack nesting and other limitations), there's no need to worry about the timer in an interrupt--just keep track of how much time has passed.