Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate UART to use DMA and UART IDLE interrupt #38

Closed
usaguerrilla opened this issue Jun 2, 2016 · 11 comments
Closed

Migrate UART to use DMA and UART IDLE interrupt #38

usaguerrilla opened this issue Jun 2, 2016 · 11 comments
Assignees

Comments

@usaguerrilla
Copy link
Collaborator

usaguerrilla commented Jun 2, 2016

AFSK modulator on release build loads CPU for 86%. I don't want UART to interrupt AFSK message generation nor I want GPS coordinates to be lost from UART.

Proposed solution:

  • migrate UART to receive using DMA feature (allocate memory for more than 1 message)
  • end of message can be detected by UART IDLE interrupt or DMA full and memory can be copied to ring buffer
  • in main() thread parse and process NMEA messages

this will remove code from interrupts and CPU will be free to handle AFSK modulation.

@usaguerrilla usaguerrilla self-assigned this Jun 2, 2016
@Scorillo47
Copy link
Collaborator

86% CPU for a modulator? We should just use a faster CPU

Sent from my Windows Phone


De la: Pavel Krupetsmailto:notifications@github.com
Trimis: ‎02.‎06.‎2016 9:47
Către: far-far-away-science/hab-v2mailto:hab-v2@noreply.github.com
Subiect: [far-far-away-science/hab-v2] Migrate UART to use DMA and UART IDLE interrupt (#38)

AFSK modulator on release build loads CPU for 86%. I don't want UART to interrupt AFSK message generation nor I want GPS coordinates to be lost from UART.

Proposed solution:

  • migrate UART to receive using DMA feature (allocate memory for more than 1 message)
  • end of message can be detected by UART IDLE interrupt and memory can be copied to ring buffer
  • in main() thread parse and process NMEA messages

this will remove code from interrupts and CPU will be free to handle AFSK modulation.


You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
#38

@usaguerrilla
Copy link
Collaborator Author

usaguerrilla commented Jun 2, 2016

I want this to work on a slowest CPU possible so code can be ported to circumnavigating balloon.

I did this test:
do ((a * b + c) / d) and write to RAM on 16MHz at 96kHz and it loaded CPU 30%. Adding read from program memory increased it to 50% so I don't think I can optimize much. Division might be slowest operation.

@usaguerrilla
Copy link
Collaborator Author

By 86% I mean CPU was running at full speed and consumed 86% of available time to fill DMA buffer.

@usaguerrilla
Copy link
Collaborator Author

Also DMA for UART will save us from getting to many interrupts which is good as well. I wasn't sure how to detect when UART finished transmitting but DMA buffer isn't full.

After reading specs it seems UART IDLE interrupt will be fired in this case and I can copy memory from DMA buffer to ring buffer for later processing.

So instead of handling interrupt for each symbol I will have 2 interrupts: UART IDLE, DMA BUFFER FULL

@Scorillo47
Copy link
Collaborator

I see. How long is the duty cycle for this computation? Maybe it's not a problem if it's very small.
BTW, I don't think this particular CPU implements hardware division - this could be an issue making the computation much longer.
Is the "d" constant, BTW? We can use tricks to divide faster by certain type of constants (bit shifts, addition, etc)
Also, the a*b + c type of expressions can be optimized to be much faster by using DSP instructions from ARM Cortex-M4 (I presume we are talking about integer operations, not floating point)

Adi

Date: Thu, 2 Jun 2016 10:10:53 -0700
From: notifications@github.com
To: hab-v2@noreply.github.com
CC: adi_oltean@hotmail.com; comment@noreply.github.com
Subject: Re: [far-far-away-science/hab-v2] Migrate UART to use DMA and UART IDLE interrupt (#38)

I want this to work on a slowest CPU possible so code can be ported to circumnavigating balloon.

I did this test:

do (a * b + c / d) and write to RAM on 16MHz at 96kHz and it loaded CPU 30%. Adding read from program memory increased it to 50% so I don't think I can optimize much. Division might be slowest operation.


You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or mute the thread.

@usaguerrilla
Copy link
Collaborator Author

We aren't using M4. AFSK modulation works so I don't see a problem. Changing to use DMA for UART also isn't a big deal.

@usaguerrilla
Copy link
Collaborator Author

optimizations for shifts and * will be done at the end when we know signal generation frequency, CPU frequency, etc. For now it's enough that it works on target CPU.

@stcarlso
Copy link
Collaborator

stcarlso commented Jun 7, 2016

The division is the killer here. Can you make it a shift? Shifts are usually free.

@usaguerrilla
Copy link
Collaborator Author

usaguerrilla commented Jun 7, 2016

Yeh. After I make sure precision for each operation is optimized I will replace divisions by shifts / muls.

n / 1'000'000 for instance will be replaced (if it stays) with ((n >> 6) * 67) >> 20).

This improves duty cycle from 86% to 40%.

I am still able to receive message from short distance with this change but need to test longer distances though.

@usaguerrilla
Copy link
Collaborator Author

Main thing is that even without this speedup code works so we can make PCB for final testing, as testing long distance with breadboard is not very clever.

@usaguerrilla
Copy link
Collaborator Author

we don't have enough DMA channels for this. Will have to live with interrupt.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants