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

[TW#16121] No easy way to know when RMT transmission has ended #1175

Closed
chanibal opened this issue Oct 27, 2017 · 13 comments
Closed

[TW#16121] No easy way to know when RMT transmission has ended #1175

chanibal opened this issue Oct 27, 2017 · 13 comments

Comments

@chanibal
Copy link
Contributor

From what I know, the only way to know when TX has ended at the moment is to completely replace RMT initialization (rmt_driver_install) with copy-pasted and slightly modified version. So it would load the, again slightly modified, rmt_driver_isr_default where finally you can tap into the event.

You could also poll the RMT struct, but that will take time and resources.

I propose an easy fix for this solution adding a handler that will fire when transmission ends, see pull request #1174

@FayeY FayeY changed the title No easy way to know when RMT transmission has ended [TW#16121] No easy way to know when RMT transmission has ended Oct 30, 2017
@koobest
Copy link
Contributor

koobest commented Nov 9, 2017

@chanibal Hi, chanibal, we have API
esp_err_t rmt_wait_tx_done(rmt_channel_t channel, TickType_t wait_time) that you can call to see if the transmission has been finished.

@chanibal
Copy link
Contributor Author

chanibal commented Nov 9, 2017

But rmt_wait_tx_done needs to be polled from a task/timer, and it's not usable in interrupt context. And knowing immediately is very usefull for two-way communication using signals generated from RMT.

In my current implementation, I need only to check if RMT has finished transmitting and don't have to execute custom logic at end of transmission. But I can't do that either, because I need to know that from ISR context, and rmt_wait_tx_done is not something that I should use there, even with wait_time=0.

@chanibal
Copy link
Contributor Author

chanibal commented Nov 9, 2017

For details on what I need this message for, look at the diagram at #1179 (note that I'm not using the so-called RMT and GPIO modes now, both of these are working simmultniously - but the algorithm is wait for falling edge, if rmt is not executing then exec rmt, start over)

@koobest
Copy link
Contributor

koobest commented Nov 19, 2017

Yes, you are right. rmt_wait_tx_done is not suitable in some cases. we do not currently have a good solution for this, but your fix is realy a good way to be taken.

@FayeY FayeY closed this as completed Nov 22, 2017
@phatpaul
Copy link
Contributor

esp_err_t rmt_wait_tx_done(rmt_channel_t channel, TickType_t wait_time) could be used for polling (with wait_time==0), but it emits an error message.

E (54406) rmt: Timeout on wait_tx_done

How should I poll for tx busy without causing the error message?

@chanibal
Copy link
Contributor Author

@phatpaul : Don't. My question is almost a year old, this has been fixed since.
You should register a callback with rmt_register_tx_end_callback.

@phatpaul
Copy link
Contributor

I see the new callback, and that will be very useful for when I need to wait for tx to be free.

But when I enter my CGI function, I would like to know immediately whether tx is busy.
(I want to know if it is busy before calling rmt_write_sample(), because that function might yield if it is busy and I don't want my http server to be blocked.)

  • If tx is not busy, I will start a RMT transmission from within the CGI function and return immediately. I don't need to wait for completion in this case.

  • If tx is busy, I will register the rmt_register_tx_end_callback callback from within the CGI function and return immediately with HTTPD_CGI_MORE to allow the http server to service other requests. When rmt_register_tx_end_callback triggers, it will resume the http server connection/CGI function.

So again, I just want to call rmt_wait_tx_done(rmt_channel_t channel, TickType_t wait_time) (with wait_time==0) to check if tx is busy, without generating an error message.

Do you think I should open a new issue for this? Thanks.

@koobest
Copy link
Contributor

koobest commented Sep 25, 2018

Hi, @phatpaul
I added an API to get the status of the RMA channel. It will be merged soon. thanks.

@r1dd1ck
Copy link

r1dd1ck commented Oct 6, 2018

ℹ️ Well, there always was the rmt_get_status(rmt_channel_t channel, uint32_t* status) function, which can be used for this (polling).

The only problem: it is nowhere documented, so barely anyone knows about it, or how to actually make use of it >_<

status & 0x1000000 --> TX busy

The bottom line: This whole issue & all of its follow-ups could have most probably been avoided, if there was proper documentation.

@koobest

I added an API to get the status of the RMT channel. It will be merged soon.

there already is one (and has been for a very long time) ... 😑
I'm just hoping you are not going to replace it 🙈

💩

@koobest
Copy link
Contributor

koobest commented Oct 9, 2018

Hi, here is the description of each field of the status register:

struct {
    uint32_t mem_waddr_ex: 10; //[9:0] The current memory read address of channel n
    uint32_t reserved10: 2; //[11:10]
    uint32_t mem_raddr_ex: 10;  //[21:12] The current memory write address of channel n
    uint32_t reserved22: 2;  //[23:22]   
    uint32_t state: 3;  //[26:24] The channel n state machine status register:
0x0 : idle, 0x1 : send, 0x2 : read memory, 0x3 : receive, 0x4 : wait.
    uint32_t mem_owner_err: 1;  //[27]  When channel n is configured for receive mode, this bit will turn to high level if rmt_mem_owner register is not set to 1.
    uint32_t mem_full: 1;  //[28]  The menory full status bit for channel n turns to high level
 when mem_waddr_ex is greater than or equal to the configuration range.
   uint32_t mem_empty: 1;  //[29]  The menory empty status bit for channel n. in acyclic mode,
 this bit turns to high level when mem_raddr_ex is greater than or equal to the configured range.
   uint32_t apb_mem_wr_err: 1;  //[30]  The apb write menory status bit for channel 2 turns to
 high level when the apb write address exceeds the configuration range.
   uint32_t apb_mem_rd_err: 1; // [31]  The apb read menory status bit for channel 2 turns to high level when the apb read address exceeds the configuration range
} status_ch_n;

we will update the TRM and the IDF soon.

thanks!!

@phatpaul
Copy link
Contributor

phatpaul commented Oct 9, 2018

Thanks for the description of the mystery status register.

But please also take a look at my pull-request. It adds some needed functions for me and probably for others too.
#2461

@johannesmaibaum
Copy link

Hi @koobest ,

...
uint32_t mem_waddr_ex: 10; //[9:0] The current memory read address of channel n
uint32_t mem_raddr_ex: 10;  //[21:12] The current memory write address of channel n
...

Is this true? Or is read/write swapped in the comments?

@koobest
Copy link
Contributor

koobest commented Oct 29, 2018

Hi, @johannesmaibaum, The comment is right. One thing to note is that the value of mem_waddr_ex and mem_waddr_ex is only valid in fifo mode,but the rmt driver uses a non-fifo mode.

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

6 participants