<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>ColdFire/68K Microcontrollers and ProcessorsのトピックRe: Coldfire, Interrupts and the &amp;quot;Halting problem&amp;quot;</title>
    <link>https://community.nxp.com/t5/ColdFire-68K-Microcontrollers/Coldfire-Interrupts-and-the-quot-Halting-problem-quot/m-p/411471#M12522</link>
    <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;P&gt;I was hoping that someone would have a try at this one. There are some important consequences, and there may be a lot of devices out there with these problems.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;This is what the inner loop compiles to:&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;PRE ___default_attr="plain" _modifiedtitle="true" class="jive_macro_code jive_text_macro" data-renderedposition="113_8_969_160"&gt;&lt;P&gt;80101eea: 280e movel %fp,%d4&lt;/P&gt;&lt;P&gt;80101ef8: 0684 ffff ff60 addil #-160,%d4&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;for (i = 0; i &amp;lt; 40; i++) {&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; counts[i] = nStuckCounter;&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;P&gt;801024d4: 2044 moveal %d4,%a0&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #3334ca;"&gt;801024d6: 2039 8080 003c movel 8080003c &amp;lt;nStuckCounter&amp;gt;,%d0&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #3334ca;"&gt;801024dc: 20c0 movel %d0,%a0@+&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #3334ca;"&gt;801024de: bdc8 cmpal %a0,%fp&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #3334ca;"&gt;801024e0: 66f4 bnes 801024d6 &amp;lt;main+0xb34&amp;gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/PRE&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;The inner loop consists of four machine code instructions. The output is thus:&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;PRE ___default_attr="plain" class="jive_macro_code jive_text_macro" data-renderedposition="336_8_969_224"&gt;&lt;P&gt;Prior to Force, nStuckCounter = 0 &lt;/P&gt;&lt;P&gt;Loop 0, nStuckCounter = 3 &lt;/P&gt;&lt;P&gt;Loop 1, nStuckCounter = 7 &lt;/P&gt;&lt;P&gt;Loop 2, nStuckCounter = 11 &lt;/P&gt;&lt;P&gt;Loop 3, nStuckCounter = 15 &lt;/P&gt;&lt;P&gt;Loop 4, nStuckCounter = 19 &lt;/P&gt;&lt;P&gt;Loop 5, nStuckCounter = 23 &lt;/P&gt;&lt;P&gt;... Loops 6 to 35 exactly as you'd expect ...&lt;/P&gt;&lt;P&gt;Loop 35, nStuckCounter = 143 &lt;/P&gt;&lt;P&gt;Loop 36, nStuckCounter = 147 &lt;/P&gt;&lt;P&gt;Loop 37, nStuckCounter = 151 &lt;/P&gt;&lt;P&gt;Loop 38, nStuckCounter = 155 &lt;/P&gt;&lt;P&gt;Loop 39, nStuckCounter = 159 &lt;/P&gt;&lt;P&gt;After Unforce, nStuckCounter = 208841 &lt;/P&gt;&lt;/PRE&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Even though the interrupt routine is "solidly stuck", the mainline gets to execute ONE instruction between each interrupt.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;So what harm could that do?&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;On pretty much any other CPU, if you have a stuck interrupt, you find out about it really quickly as the device locks up solid in the interrupt routine. It doesn't get out of the door with a bug like that.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;With THESE CPUs, the code still runs! It runs between 10 and 100 times slower than usual, depending on how many instructions the interrupt service routine has in it, but it RUNS. It runs slower than when you forget to enable the Program Cache (in the higher end and faster chips that have that). So if you're wondering why your code is running slower than you think it should be, maybe you have a stuck interrupt. Or you should turn the cache on. Or both.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;I found this due to a different problem. The code it was running was a simple multi-threaded system using setjmp() and longjmp(), but with preemption from a high priority timer interrupt, that forced a lower priority interrupt to perform the context switch. The secondary thread looks like this (example, WAY simplified):&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;PRE ___default_attr="c++" _modifiedtitle="true" class="jive_macro_code jive_text_macro" data-renderedposition="875_8_969_208"&gt;&lt;P&gt;static void task_loop(sTask_t *a_psTask)&lt;/P&gt;&lt;P&gt;{&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; while (true)&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="color: #e23d39;"&gt;a_psTask-&amp;gt;eState = TASK_STATE_RUN&lt;/SPAN&gt;;&amp;nbsp;&amp;nbsp; /* Allow switching */&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (*(a_psTask-&amp;gt;pTaskFunc))(a_psTask-&amp;gt;pUserRef);&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="color: #7ed529;"&gt;a_psTask-&amp;gt;eState = TASK_STATE_IDLE;&amp;nbsp; /* Disallow switching */&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (setjmp(a_psTask-&amp;gt;sContextTask) == 0)&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; longjmp(a_psTask-&amp;gt;sContextMain, 1);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;/PRE&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;When the timer goes off it check the "psTask-&amp;gt;eState", and only forces a switch if it is "TASK_STATE_RUN". "TASK_STATE_IDLE" means "don't switch, I'm about to do it myself".&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;The higher priority interrupt checked for that and scheduled the lower priority one. It all went wrong if there were a bunch of medium priority interrupts (Ethernet, CAN, serial port) that got in between those other two interrupts. They allowed the code above to step into the "setjmp()" at one instruction per intervening interrupt. When the second interrupt went off it called "setjmp()" in the middle of the above call which corrupted the context, later causing a stack corruption.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;The simple fixes were to have the second interrupt check "psTask-&amp;gt;eState" or to disable interrupts completely around the switch.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;So where's this in the Reference Manual? Nowhere that I can find. The CFPRM's documentation of "RTE" says that it restores the state, but doesn't say if a subsequent interrupt happens before or after that instruction is executed. The way it works may be a side-effect of this feature:&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P style="padding-left: 30px;"&gt;&lt;STRONG style="font-family: courier new,courier;"&gt;ColdFire Family Programmer’s Reference Manual, Rev. 3&lt;/STRONG&gt;&lt;/P&gt;&lt;P style="padding-left: 30px;"&gt;&lt;STRONG style="font-family: courier new,courier;"&gt;Chapter 11&lt;/STRONG&gt;&lt;/P&gt;&lt;P style="padding-left: 30px;"&gt;&lt;STRONG style="font-family: courier new,courier;"&gt;Exception Processing&lt;/STRONG&gt;&lt;/P&gt;&lt;P style="padding-left: 30px;"&gt;&lt;STRONG style="font-family: courier new,courier;"&gt;11.1 Overview&lt;/STRONG&gt;&lt;/P&gt;&lt;P style="padding-left: 30px;"&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;ColdFire processors inhibit sampling for interrupts during the first instruction of all exception handlers.&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="padding-left: 30px;"&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;This allows any handler to effectively disable interrupts, if necessary, by raising the interrupt mask level&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="padding-left: 30px;"&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;in the SR.&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="padding-left: 30px;"&gt;&lt;/P&gt;&lt;P&gt;And also it seems for the first instruction executed on any exception return.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Don't trust the "Auto Save" on this forum. It just lost me an hour's work and the "Auto Save" had only saved the first minute or two. Fortunately I copy/save to the clipboard regularly, and that saved me from having to type it all in again.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Tom&lt;/P&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
    <pubDate>Tue, 12 May 2015 12:21:09 GMT</pubDate>
    <dc:creator>TomE</dc:creator>
    <dc:date>2015-05-12T12:21:09Z</dc:date>
    <item>
      <title>Coldfire, Interrupts and the "Halting problem"</title>
      <link>https://community.nxp.com/t5/ColdFire-68K-Microcontrollers/Coldfire-Interrupts-and-the-quot-Halting-problem-quot/m-p/411470#M12521</link>
      <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;P&gt;I've been working on a nasty problem on an MCF5235 for about 2 weeks, and what I've found might help others.&lt;/P&gt;&lt;P style="min-height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;If you don't know the background to "The Halting Problem" you might want to read up on it a bit. It isn't about "Halting", but deciding, by inspection, if a particular program will run the way you expect it to.&lt;/P&gt;&lt;P style="min-height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I've just found a simple class of program that doesn't run the way I'd expect it to on the MCF5235, and what it actually did resulted in stack corruption and crashes.&lt;/P&gt;&lt;P style="min-height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;It could also result in a buggy program running, but really S L O W L Y and without any obvious reason for it running like that.&lt;/P&gt;&lt;P style="min-height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Here's an example program. The critical part of this is that it triggers an interrupt, but then doesn't clear it. For simplicity this code is using the "MCF_INTC0_INTFRCL" Interrupt Forcing registers, but forgetting to clear a Peripheral Interrupt would do the same thing.&lt;/P&gt;&lt;P style="min-height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;So, by inspection, what would you experienced Coldfire programmers expect to happen when I run the following code? All 29 of you following this forum apparently.&lt;/P&gt;&lt;P style="min-height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;When I've accidentally done this on other CPUs I've used, the code is now stuck continuously executing the interrupt service routine, and the watchdog usually goes off some time later.&lt;/P&gt;&lt;P style="min-height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/P&gt;&lt;PRE class="c++" name="code"&gt;volatile int nStuckCounter = 0;&amp;nbsp; __attribute__((interrupt_handler)) static void stuck_int(void) { /*&amp;nbsp; INT_UNFORCE(int_task_switch); */&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; nStuckCounter += 1; }&amp;nbsp; void test(void) { &amp;nbsp;&amp;nbsp;&amp;nbsp; int i;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; INT_SET_VECTOR(int_task_switch, stuck_int);&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; printf("Prior to Force, nStuckCounter = %u\n", nStuckCounter);&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; INT_FORCE(int_task_switch);&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; for (i = 0; i &amp;lt; 40; i++) { &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; counts[i] = nStuckCounter; &amp;nbsp;&amp;nbsp;&amp;nbsp; } &amp;nbsp;&amp;nbsp;&amp;nbsp; for (i = 0; i &amp;lt; 40; i++) { &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; printf("Loop %d, nStuckCounter = %d\n", i, counts[i]); &amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; INT_UNFORCE(int_task_switch);&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; printf("After Unforce, nStuckCounter = %u\n", nStuckCounter); }&lt;/PRE&gt;&lt;DIV style="display:none;"&gt; &lt;/DIV&gt;&lt;P style="min-height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Note:&lt;/P&gt;&lt;OL&gt;&lt;LI&gt;If it locked up like I expected I wouldn't be asking.&lt;/LI&gt;&lt;LI&gt;In the Interrupt Service Routine the proper thing to do is to clear the "Force" using the "INT_UNFORCE()" macro, but I've deliberately commented that out.&lt;/LI&gt;&lt;LI&gt;"INT_FORCE", "INT_UNFORCE" and "INT_SET_VECTOR" work as expected. They're not important and not a problem here.&lt;/LI&gt;&lt;LI&gt;"printf()" works as expected (polled printing to the serial port)&lt;/LI&gt;&lt;/OL&gt;&lt;P style="min-height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;For "bonus points", here's the disassembly of the counting loop above, and with that information you should be able to tell me what the printed "nStuckCounter" values will be...&lt;/P&gt;&lt;P style="min-height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;If I could paste disassembly into this forum, but after years of complaining about not being able to simply "paste code", and TWO "updates" this forum STILL can't do that. It is trying to paste the disassembly into a table and then word-wrapping and mangling it!&lt;/P&gt;&lt;P style="min-height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;More multiple tries (you can't see how long this took). I had to manually remove all the spaces, paste it in and then reinstate all the spaces. Now it looks OK.&lt;/P&gt;&lt;P style="min-height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/P&gt;&lt;PRE class="plain" name="code"&gt;80101eea: 280e&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; movel %fp,%d4 80101ef8: 0684 ffff ff60 addil #-160,%d4&amp;nbsp; for (i = 0; i &amp;lt; 40; i++) { &amp;nbsp;&amp;nbsp;&amp;nbsp; counts[i] = nStuckCounter; } 801024d4: 2044&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; moveal %d4,%a0 801024d6: 2039 8080 003c movel 8080003c &amp;lt;nStuckCounter&amp;gt;,%d0 801024dc: 20c0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; movel %d0,%a0@+ 801024de: bdc8&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cmpal %a0,%fp 801024e0: 66f4&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; bnes 801024d6 &amp;lt;main+0xb34&amp;gt;&lt;/PRE&gt;&lt;DIV style="display:none;"&gt; &lt;/DIV&gt;&lt;P style="min-height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I'll post the printout I have next week.&lt;/P&gt;&lt;P style="min-height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;More bonus points. Where, and in what manual is this behaviour documented?&lt;/P&gt;&lt;P style="min-height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Tom&lt;/P&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
      <pubDate>Fri, 08 May 2015 02:05:36 GMT</pubDate>
      <guid>https://community.nxp.com/t5/ColdFire-68K-Microcontrollers/Coldfire-Interrupts-and-the-quot-Halting-problem-quot/m-p/411470#M12521</guid>
      <dc:creator>TomE</dc:creator>
      <dc:date>2015-05-08T02:05:36Z</dc:date>
    </item>
    <item>
      <title>Re: Coldfire, Interrupts and the "Halting problem"</title>
      <link>https://community.nxp.com/t5/ColdFire-68K-Microcontrollers/Coldfire-Interrupts-and-the-quot-Halting-problem-quot/m-p/411471#M12522</link>
      <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;P&gt;I was hoping that someone would have a try at this one. There are some important consequences, and there may be a lot of devices out there with these problems.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;This is what the inner loop compiles to:&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;PRE ___default_attr="plain" _modifiedtitle="true" class="jive_macro_code jive_text_macro" data-renderedposition="113_8_969_160"&gt;&lt;P&gt;80101eea: 280e movel %fp,%d4&lt;/P&gt;&lt;P&gt;80101ef8: 0684 ffff ff60 addil #-160,%d4&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;for (i = 0; i &amp;lt; 40; i++) {&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; counts[i] = nStuckCounter;&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;P&gt;801024d4: 2044 moveal %d4,%a0&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #3334ca;"&gt;801024d6: 2039 8080 003c movel 8080003c &amp;lt;nStuckCounter&amp;gt;,%d0&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #3334ca;"&gt;801024dc: 20c0 movel %d0,%a0@+&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #3334ca;"&gt;801024de: bdc8 cmpal %a0,%fp&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #3334ca;"&gt;801024e0: 66f4 bnes 801024d6 &amp;lt;main+0xb34&amp;gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/PRE&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;The inner loop consists of four machine code instructions. The output is thus:&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;PRE ___default_attr="plain" class="jive_macro_code jive_text_macro" data-renderedposition="336_8_969_224"&gt;&lt;P&gt;Prior to Force, nStuckCounter = 0 &lt;/P&gt;&lt;P&gt;Loop 0, nStuckCounter = 3 &lt;/P&gt;&lt;P&gt;Loop 1, nStuckCounter = 7 &lt;/P&gt;&lt;P&gt;Loop 2, nStuckCounter = 11 &lt;/P&gt;&lt;P&gt;Loop 3, nStuckCounter = 15 &lt;/P&gt;&lt;P&gt;Loop 4, nStuckCounter = 19 &lt;/P&gt;&lt;P&gt;Loop 5, nStuckCounter = 23 &lt;/P&gt;&lt;P&gt;... Loops 6 to 35 exactly as you'd expect ...&lt;/P&gt;&lt;P&gt;Loop 35, nStuckCounter = 143 &lt;/P&gt;&lt;P&gt;Loop 36, nStuckCounter = 147 &lt;/P&gt;&lt;P&gt;Loop 37, nStuckCounter = 151 &lt;/P&gt;&lt;P&gt;Loop 38, nStuckCounter = 155 &lt;/P&gt;&lt;P&gt;Loop 39, nStuckCounter = 159 &lt;/P&gt;&lt;P&gt;After Unforce, nStuckCounter = 208841 &lt;/P&gt;&lt;/PRE&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Even though the interrupt routine is "solidly stuck", the mainline gets to execute ONE instruction between each interrupt.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;So what harm could that do?&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;On pretty much any other CPU, if you have a stuck interrupt, you find out about it really quickly as the device locks up solid in the interrupt routine. It doesn't get out of the door with a bug like that.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;With THESE CPUs, the code still runs! It runs between 10 and 100 times slower than usual, depending on how many instructions the interrupt service routine has in it, but it RUNS. It runs slower than when you forget to enable the Program Cache (in the higher end and faster chips that have that). So if you're wondering why your code is running slower than you think it should be, maybe you have a stuck interrupt. Or you should turn the cache on. Or both.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;I found this due to a different problem. The code it was running was a simple multi-threaded system using setjmp() and longjmp(), but with preemption from a high priority timer interrupt, that forced a lower priority interrupt to perform the context switch. The secondary thread looks like this (example, WAY simplified):&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;PRE ___default_attr="c++" _modifiedtitle="true" class="jive_macro_code jive_text_macro" data-renderedposition="875_8_969_208"&gt;&lt;P&gt;static void task_loop(sTask_t *a_psTask)&lt;/P&gt;&lt;P&gt;{&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; while (true)&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="color: #e23d39;"&gt;a_psTask-&amp;gt;eState = TASK_STATE_RUN&lt;/SPAN&gt;;&amp;nbsp;&amp;nbsp; /* Allow switching */&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (*(a_psTask-&amp;gt;pTaskFunc))(a_psTask-&amp;gt;pUserRef);&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="color: #7ed529;"&gt;a_psTask-&amp;gt;eState = TASK_STATE_IDLE;&amp;nbsp; /* Disallow switching */&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (setjmp(a_psTask-&amp;gt;sContextTask) == 0)&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; longjmp(a_psTask-&amp;gt;sContextMain, 1);&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;P&gt;}&lt;/P&gt;&lt;/PRE&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;When the timer goes off it check the "psTask-&amp;gt;eState", and only forces a switch if it is "TASK_STATE_RUN". "TASK_STATE_IDLE" means "don't switch, I'm about to do it myself".&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;The higher priority interrupt checked for that and scheduled the lower priority one. It all went wrong if there were a bunch of medium priority interrupts (Ethernet, CAN, serial port) that got in between those other two interrupts. They allowed the code above to step into the "setjmp()" at one instruction per intervening interrupt. When the second interrupt went off it called "setjmp()" in the middle of the above call which corrupted the context, later causing a stack corruption.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;The simple fixes were to have the second interrupt check "psTask-&amp;gt;eState" or to disable interrupts completely around the switch.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;So where's this in the Reference Manual? Nowhere that I can find. The CFPRM's documentation of "RTE" says that it restores the state, but doesn't say if a subsequent interrupt happens before or after that instruction is executed. The way it works may be a side-effect of this feature:&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P style="padding-left: 30px;"&gt;&lt;STRONG style="font-family: courier new,courier;"&gt;ColdFire Family Programmer’s Reference Manual, Rev. 3&lt;/STRONG&gt;&lt;/P&gt;&lt;P style="padding-left: 30px;"&gt;&lt;STRONG style="font-family: courier new,courier;"&gt;Chapter 11&lt;/STRONG&gt;&lt;/P&gt;&lt;P style="padding-left: 30px;"&gt;&lt;STRONG style="font-family: courier new,courier;"&gt;Exception Processing&lt;/STRONG&gt;&lt;/P&gt;&lt;P style="padding-left: 30px;"&gt;&lt;STRONG style="font-family: courier new,courier;"&gt;11.1 Overview&lt;/STRONG&gt;&lt;/P&gt;&lt;P style="padding-left: 30px;"&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;ColdFire processors inhibit sampling for interrupts during the first instruction of all exception handlers.&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="padding-left: 30px;"&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;This allows any handler to effectively disable interrupts, if necessary, by raising the interrupt mask level&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="padding-left: 30px;"&gt;&lt;SPAN style="font-family: courier new,courier;"&gt;in the SR.&lt;/SPAN&gt;&lt;/P&gt;&lt;P style="padding-left: 30px;"&gt;&lt;/P&gt;&lt;P&gt;And also it seems for the first instruction executed on any exception return.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Don't trust the "Auto Save" on this forum. It just lost me an hour's work and the "Auto Save" had only saved the first minute or two. Fortunately I copy/save to the clipboard regularly, and that saved me from having to type it all in again.&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;Tom&lt;/P&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
      <pubDate>Tue, 12 May 2015 12:21:09 GMT</pubDate>
      <guid>https://community.nxp.com/t5/ColdFire-68K-Microcontrollers/Coldfire-Interrupts-and-the-quot-Halting-problem-quot/m-p/411471#M12522</guid>
      <dc:creator>TomE</dc:creator>
      <dc:date>2015-05-12T12:21:09Z</dc:date>
    </item>
  </channel>
</rss>

