Just asking...
USART3 Interrupt Grabbing?
(28 posts) (8 voices)-
Posted 4 years ago #
-
bubulindo - I apologise if my answer was a bit more than you wanted.
I try to answer questions in a way that might help the poster, and future forum readers who want answers to similar questions.
IMHO the accurate technical answer (no, it isn't needed in that specific context), isn't all the issues to consider for someone who is looking to answer this sort of question. There would not be an error message if the interrupt handler is not linked in, so testing and debugging can be confusing and worrying, and reusing the code is a bit delicate. So I think those things are worth mentioning too.Posted 4 years ago # -
No worries.
Written words look different than they would sound.Thanks for the info.
Posted 4 years ago # -
By the way, what if we create a .c file/library? Do we need to include the irq handler in the extern C block?
In general, IRQ handlers need C linkage. Within a C++ file, this means you either put them within an extern "C" block, or you declare them extern "C" with
extern "C" void __irq_whatever(void) { ... }
Within a C file, they'll have C linkage already, so the extern linkage specifier is unnecessary.
Regarding how to release code which overrides IRQ handlers as a library, this is currently a pain, since you have to get your users to comment out the handlers in the copy of libmaple that comes with the IDE. That's obviously not ideal, so in the next version, we'll be making the libmaple IRQ handlers weak, so you can override them just by declaring your own.
Posted 4 years ago # -
Hi guys! I'm trying to receive DMX too, but I want to use DMA for this, to free the processor for the other tasks. And I plan to use the USART frame error interrupt to start the DMA transfer. But the Maple hangs up at first interrupt.
The program must receive DMX data and print to the SerialUSB first 10 channels, so I can see does it receive anything or not. If I disable the interrups and put the DMA in cycle mode, within that 10 channels I sometimes see the data that I send to the DMX input, so the DMA is working (but the 1st channel of DMX data may appear in any array element). But when I enable the USART interrups (rising 1st bit of the CR3), the program prints zero values when no DMX data at the input, and hangs when I connect the DMX cable. What may be wrong? Here's the code:
#include "dma.h" #define dmxSerial Serial3 // USART class #define dmxBase USART3_BASE // USART regesters #define dmxInDMA DMA_CH3 // DMA channel uint32 lm; byte dmx[513]; volatile uint8 a; extern "C" { void __irq_usart3(void) { if (dmxBase->SR & USART_SR_FE) { // break dma_disable(DMA1, dmxInDMA); a = dmxBase->DR; // clear error flag a = a; // for compiler not to make warning dma_set_mem_addr(DMA1, dmxInDMA, &dmx); dma_set_num_transfers(DMA1, dmxInDMA, 513); dma_enable(DMA1, dmxInDMA); } } } void setup() { dmxSerial.begin(250000); dmxBase->CR2 |= USART_CR2_STOP_BITS_2; dmxBase->CR3 |= USART_CR3_DMAT; dmxBase->CR3 |= USART_CR3_DMAR; dmxBase->CR1 &= 0b1111111000001111; // disable interrupts dmxBase->CR2 &= 0b1111111110111111; // disable interrupts dmxBase->CR3 |= 1; // enable error interrupt dma_init(DMA1); dma_setup_transfer(DMA1, dmxInDMA, &dmxBase->DR, DMA_SIZE_8BITS, &dmx, DMA_SIZE_8BITS, DMA_MINC_MODE); dma_set_num_transfers(DMA1, dmxInDMA, 513); lm = millis(); pinMode(22, OUTPUT); digitalWrite(22, LOW); // MAX485 receive enable } void loop() { if (millis()>lm+500) { lm = millis(); for (int i=0; i<10; i++) { SerialUSB.print(dmx[i],DEC); SerialUSB.print(", "); } SerialUSB.println(); } }
(Edit: I added code layout markup hopefully making it easier to read - gbulmer)
Posted 3 years ago # -
i tried out the code provided by brettlevine and changed it to use usart1 and commented out the appropriate lines in the usart.c.
i do get data on the usart1 line but it is not consistent. not all 8 channels always receive data, or not the same data.
i have a real dmx receiving light dimmer on the same dmx line which allows me to see if the data i am sending from the PC is correct.?
Posted 2 years ago # -
i finally got brettlevine's code working. i will posted it eventually but at this point i forgot what i did different.
i thing i am noticing is that the channels sequence shifts sometimes.
i have the pc fade only one channel and the channels stay at zero. on the maple the connected led fades nicely but sometimes the lower channel gets its value.for example here is a print out of 5 channels
0 0 0 122 0
0 0 0 122 0
0 0 0 122 0
0 0 122 0 0
0 0 0 122 0this error happens more often the higher the channel numbers are.
i am guessing that somewhere in this section of the code channels are being skipped?
case DMX_START: dmx_addr++; if (dmx_addr == dmx_start_addr) { chan_cnt = 0; dmx_data[chan_cnt++] = constrain(data,0,maxDMXvalue); //data; dmx_state = DMX_RUN; } break; case DMX_RUN: dmx_data[chan_cnt++] = constrain(data,0,maxDMXvalue); //data; if (chan_cnt >= DMX_NUM_CHANNELS) { dmx_state = DMX_IDLE; } break;
what can i do about this?
thanks.
Posted 2 years ago # -
i had a bunch of stuff in loop()
taking that out helped to make this more stable.
Posted 2 years ago # -
stephanschulz - can you try to attack the problem using some throw-away code?
The symptoms might indicate characters are being lost.
This might be because of using USB for output, or other interrupts (for example USB or Systick).
So don't print to USB, and switch off USB, and Systick interrupts (IIRC there isn't anything else).My thought, which might be a bit too simple, is to write code which 'knows' what the data looks like, and which does nothing except for validating the DMX packets, after switching off everything else. The checking code would run for several hundred (or many thousand) iterations, and just count the number of errors. At the end of its iterations it would indicate the number of errors, maybe by lighting some combination of LEDs (or down a serial port if you can read it).
Start the test at a slow transmission speed, and crank it up. If it runs at the current speed without error, then printing to USB or the other interrupts might be the cause.
Posted 2 years ago # -
it seems i got it all up and running.
- 16 LEDs can be dimmed NOT using the build in PWM mode
- DMX data is receivedPosted 2 years ago # -
This forum post doesn't quite resolve this issue for me.
What is the correct method for overriding default interrupt handlers?
For example, I get multiple definitions errors of __irq_usart1 in the maple IDE unless I go in and comment out the code in the library usart.c
It doesn't seem like there's currently any method or compiler macro in libmaple is this the case?
Posted 2 years ago # -
@konan
did you ever get your DMX code working by using DMA channels? want to share what your got?i know the maple is dead but other ARM micros like the Teensy might benefit from a DMA - DMX library :)
thanks,
stephan.Posted 8 months ago # -
While LeaqfLabs have 'end of lifed' their production of the product, it is still easy to get Maple or Maple mini, that is part of the potential power of Open Source Hardware.
For example search for "leaflabs maple" at eBay.
Mini's are under $5.So, IMHO, it is still worth sharing code, and, as @stephanschulz has written, it might also be ported to other manufacturers MCUs.
I would add, AFAICT, DMA varies between different manufacturers, so it will take a bit of work to move to other manufacturers MCUs. Also, ST Micro's Nucleo's are 'cheap as chips', so that might provider another path to make low-level code available.
(Full disclosure: I am not a member of LeafLabs staff)
Posted 8 months ago #
Reply
You must log in to post.