Add an aditional (void *) arg to the RMT callback (much like Ticker() et.al.). (#3345)
* Add an aditional (void *) arg to the RMT callback - to allow more flexible handling of the callback (e.g. by passing a private struct or a class pointer). Same pattern as used by the Ticker() and many others. Example updated & new example with a trapoline added. * Fix example for new API * Fix lint warnings * Add a second missed example. * Correct timeout & improve socket error handling.
This commit is contained in:
parent
831f0ac29a
commit
d79a1f3d10
@ -94,6 +94,7 @@ struct rmt_obj_s
|
|||||||
transaction_state_t tx_state;
|
transaction_state_t tx_state;
|
||||||
rmt_rx_data_cb_t cb;
|
rmt_rx_data_cb_t cb;
|
||||||
bool data_alloc;
|
bool data_alloc;
|
||||||
|
void * arg;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -104,14 +105,14 @@ static xSemaphoreHandle g_rmt_objlocks[MAX_CHANNELS] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static rmt_obj_t g_rmt_objects[MAX_CHANNELS] = {
|
static rmt_obj_t g_rmt_objects[MAX_CHANNELS] = {
|
||||||
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false},
|
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false, NULL},
|
||||||
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false},
|
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false, NULL},
|
||||||
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false},
|
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false, NULL},
|
||||||
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false},
|
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false, NULL},
|
||||||
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false},
|
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false, NULL},
|
||||||
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false},
|
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false, NULL},
|
||||||
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false},
|
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false, NULL},
|
||||||
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false},
|
{ false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false, NULL},
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -324,6 +325,7 @@ bool rmtReadData(rmt_obj_t* rmt, uint32_t* data, size_t size)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool rmtBeginReceive(rmt_obj_t* rmt)
|
bool rmtBeginReceive(rmt_obj_t* rmt)
|
||||||
{
|
{
|
||||||
if (!rmt) {
|
if (!rmt) {
|
||||||
@ -357,7 +359,7 @@ bool rmtReceiveCompleted(rmt_obj_t* rmt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rmtRead(rmt_obj_t* rmt, rmt_rx_data_cb_t cb)
|
bool rmtRead(rmt_obj_t* rmt, rmt_rx_data_cb_t cb, void * arg)
|
||||||
{
|
{
|
||||||
if (!rmt && !cb) {
|
if (!rmt && !cb) {
|
||||||
return false;
|
return false;
|
||||||
@ -365,6 +367,7 @@ bool rmtRead(rmt_obj_t* rmt, rmt_rx_data_cb_t cb)
|
|||||||
int channel = rmt->channel;
|
int channel = rmt->channel;
|
||||||
|
|
||||||
RMT_MUTEX_LOCK(channel);
|
RMT_MUTEX_LOCK(channel);
|
||||||
|
rmt->arg = arg;
|
||||||
rmt->intr_mode = E_RX_INTR;
|
rmt->intr_mode = E_RX_INTR;
|
||||||
rmt->tx_state = E_FIRST_HALF;
|
rmt->tx_state = E_FIRST_HALF;
|
||||||
rmt->cb = cb;
|
rmt->cb = cb;
|
||||||
@ -391,6 +394,19 @@ bool rmtRead(rmt_obj_t* rmt, rmt_rx_data_cb_t cb)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool rmtEnd(rmt_obj_t* rmt) {
|
||||||
|
if (!rmt) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int channel = rmt->channel;
|
||||||
|
|
||||||
|
RMT_MUTEX_LOCK(channel);
|
||||||
|
RMT.conf_ch[channel].conf1.rx_en = 1;
|
||||||
|
RMT_MUTEX_UNLOCK(channel);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool rmtReadAsync(rmt_obj_t* rmt, rmt_data_t* data, size_t size, void* eventFlag, bool waitForData, uint32_t timeout)
|
bool rmtReadAsync(rmt_obj_t* rmt, rmt_data_t* data, size_t size, void* eventFlag, bool waitForData, uint32_t timeout)
|
||||||
{
|
{
|
||||||
if (!rmt) {
|
if (!rmt) {
|
||||||
@ -523,6 +539,8 @@ rmt_obj_t* rmtInit(int pin, bool tx_not_rx, rmt_reserve_memsize_t memsize)
|
|||||||
rmt->tx_not_rx = tx_not_rx;
|
rmt->tx_not_rx = tx_not_rx;
|
||||||
rmt->buffers =buffers;
|
rmt->buffers =buffers;
|
||||||
rmt->channel = channel;
|
rmt->channel = channel;
|
||||||
|
rmt->arg = NULL;
|
||||||
|
|
||||||
_initPin(pin, channel, tx_not_rx);
|
_initPin(pin, channel, tx_not_rx);
|
||||||
|
|
||||||
// Initialize the registers in default mode:
|
// Initialize the registers in default mode:
|
||||||
@ -544,6 +562,7 @@ rmt_obj_t* rmtInit(int pin, bool tx_not_rx, rmt_reserve_memsize_t memsize)
|
|||||||
RMT.conf_ch[channel].conf1.idle_out_lv = 0; // signal level for idle
|
RMT.conf_ch[channel].conf1.idle_out_lv = 0; // signal level for idle
|
||||||
RMT.conf_ch[channel].conf1.idle_out_en = 1; // enable idle
|
RMT.conf_ch[channel].conf1.idle_out_en = 1; // enable idle
|
||||||
RMT.conf_ch[channel].conf1.ref_always_on = 0; // base clock
|
RMT.conf_ch[channel].conf1.ref_always_on = 0; // base clock
|
||||||
|
|
||||||
RMT.apb_conf.fifo_mask = 1;
|
RMT.apb_conf.fifo_mask = 1;
|
||||||
|
|
||||||
if (tx_not_rx) {
|
if (tx_not_rx) {
|
||||||
@ -659,7 +678,7 @@ static void IRAM_ATTR _rmt_isr(void* arg)
|
|||||||
}
|
}
|
||||||
if (g_rmt_objects[ch].cb) {
|
if (g_rmt_objects[ch].cb) {
|
||||||
// actually received data ptr
|
// actually received data ptr
|
||||||
(g_rmt_objects[ch].cb)(data_received, _rmt_get_mem_len(ch));
|
(g_rmt_objects[ch].cb)(data_received, _rmt_get_mem_len(ch), g_rmt_objects[ch].arg);
|
||||||
|
|
||||||
// restart the reception
|
// restart the reception
|
||||||
RMT.conf_ch[ch].conf1.mem_owner = 1;
|
RMT.conf_ch[ch].conf1.mem_owner = 1;
|
||||||
|
@ -40,7 +40,7 @@ typedef enum {
|
|||||||
|
|
||||||
typedef struct rmt_obj_s rmt_obj_t;
|
typedef struct rmt_obj_s rmt_obj_t;
|
||||||
|
|
||||||
typedef void (*rmt_rx_data_cb_t)(uint32_t *data, size_t len);
|
typedef void (*rmt_rx_data_cb_t)(uint32_t *data, size_t len, void *arg);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
union {
|
union {
|
||||||
@ -90,8 +90,13 @@ bool rmtReadAsync(rmt_obj_t* rmt, rmt_data_t* data, size_t size, void* eventFlag
|
|||||||
* and callback with data from ISR
|
* and callback with data from ISR
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
bool rmtRead(rmt_obj_t* rmt, rmt_rx_data_cb_t cb);
|
bool rmtRead(rmt_obj_t* rmt, rmt_rx_data_cb_t cb, void * arg);
|
||||||
|
|
||||||
|
/***
|
||||||
|
* Ends async receive started with rmtRead(); but does not
|
||||||
|
* rmtDeInit().
|
||||||
|
*/
|
||||||
|
bool rmtEnd(rmt_obj_t* rmt);
|
||||||
|
|
||||||
/* Additional interface */
|
/* Additional interface */
|
||||||
|
|
||||||
|
64
libraries/ESP32/examples/RMT/RMTCallback/RMTCallback.ino
Normal file
64
libraries/ESP32/examples/RMT/RMTCallback/RMTCallback.ino
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#include "Arduino.h"
|
||||||
|
#include "esp32-hal.h"
|
||||||
|
|
||||||
|
extern "C" void receive_trampoline(uint32_t *data, size_t len, void * arg);
|
||||||
|
|
||||||
|
class MyProcessor {
|
||||||
|
private:
|
||||||
|
rmt_obj_t* rmt_recv = NULL;
|
||||||
|
float realNanoTick;
|
||||||
|
uint32_t buff; // rolling buffer of most recent 32 bits.
|
||||||
|
int at = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
MyProcessor(uint8_t pin, float nanoTicks) {
|
||||||
|
assert((rmt_recv = rmtInit(21, false, RMT_MEM_192)));
|
||||||
|
|
||||||
|
realNanoTick = rmtSetTick(rmt_recv, nanoTicks);
|
||||||
|
};
|
||||||
|
void begin() {
|
||||||
|
rmtRead(rmt_recv, receive_trampoline, this);
|
||||||
|
};
|
||||||
|
|
||||||
|
void process(rmt_data_t *data, size_t len) {
|
||||||
|
for (int i = 0; len; len--) {
|
||||||
|
if (data[i].duration0 == 0)
|
||||||
|
break;
|
||||||
|
buff = (buff << 1) | (data[i].level0 ? 1 : 0);
|
||||||
|
i++;
|
||||||
|
|
||||||
|
if (data[i].duration1 == 0)
|
||||||
|
break;
|
||||||
|
buff = (buff << 1) | (data[i].level1 ? 1 : 0);
|
||||||
|
i++;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
uint32_t val() {
|
||||||
|
return buff;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void receive_trampoline(uint32_t *data, size_t len, void * arg)
|
||||||
|
{
|
||||||
|
MyProcessor * p = (MyProcessor *)arg;
|
||||||
|
p->process((rmt_data_t*) data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attach 3 processors to GPIO 4, 5 and 10 with different tick/speeds.
|
||||||
|
MyProcessor mp1 = MyProcessor(4, 1000);
|
||||||
|
MyProcessor mp2 = MyProcessor(5, 1000);
|
||||||
|
MyProcessor mp3 = MyProcessor(10, 500);
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
Serial.begin(115200);
|
||||||
|
mp1.begin();
|
||||||
|
mp2.begin();
|
||||||
|
mp3.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
Serial.printf("GPIO 4: %08x 5: %08x 6: %08x\n", mp1.val(), mp2.val(), mp3.val());
|
||||||
|
delay(500);
|
||||||
|
}
|
@ -172,7 +172,7 @@ void parseRmt(rmt_data_t* items, size_t len, uint32_t* channels){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void receive_data(uint32_t *data, size_t len)
|
extern "C" void receive_data(uint32_t *data, size_t len, void * arg)
|
||||||
{
|
{
|
||||||
parseRmt((rmt_data_t*) data, len, channels);
|
parseRmt((rmt_data_t*) data, len, channels);
|
||||||
}
|
}
|
||||||
@ -192,7 +192,7 @@ void setup()
|
|||||||
Serial.printf("real tick set to: %fns\n", realTick);
|
Serial.printf("real tick set to: %fns\n", realTick);
|
||||||
|
|
||||||
// Ask to start reading
|
// Ask to start reading
|
||||||
rmtRead(rmt_recv, receive_data);
|
rmtRead(rmt_recv, receive_data, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop()
|
void loop()
|
||||||
|
@ -80,12 +80,16 @@ int start_ssl_client(sslclient_context *ssl_client, const char *host, uint32_t p
|
|||||||
|
|
||||||
if (lwip_connect(ssl_client->socket, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == 0) {
|
if (lwip_connect(ssl_client->socket, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == 0) {
|
||||||
if(timeout <= 0){
|
if(timeout <= 0){
|
||||||
timeout = 30000;
|
timeout = 30000; // Milli seconds.
|
||||||
}
|
}
|
||||||
lwip_setsockopt(ssl_client->socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
|
timeval so_timeout = { .tv_sec = timeout / 1000, .tv_usec = (timeout % 1000) * 1000 };
|
||||||
lwip_setsockopt(ssl_client->socket, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
|
|
||||||
lwip_setsockopt(ssl_client->socket, IPPROTO_TCP, TCP_NODELAY, &enable, sizeof(enable));
|
#define ROE(x,msg) { if (((x)<0)) { log_e("LWIP Socket config of " msg " failed."); return -1; }}
|
||||||
lwip_setsockopt(ssl_client->socket, SOL_SOCKET, SO_KEEPALIVE, &enable, sizeof(enable));
|
ROE(lwip_setsockopt(ssl_client->socket, SOL_SOCKET, SO_RCVTIMEO, &so_timeout, sizeof(so_timeout)),"SO_RCVTIMEO");
|
||||||
|
ROE(lwip_setsockopt(ssl_client->socket, SOL_SOCKET, SO_SNDTIMEO, &so_timeout, sizeof(so_timeout)),"SO_SNDTIMEO");
|
||||||
|
|
||||||
|
ROE(lwip_setsockopt(ssl_client->socket, IPPROTO_TCP, TCP_NODELAY, &enable, sizeof(enable)),"TCP_NODELAY");
|
||||||
|
ROE(lwip_setsockopt(ssl_client->socket, SOL_SOCKET, SO_KEEPALIVE, &enable, sizeof(enable)),"SO_KEEPALIVE");
|
||||||
} else {
|
} else {
|
||||||
log_e("Connect to Server failed!");
|
log_e("Connect to Server failed!");
|
||||||
return -1;
|
return -1;
|
||||||
|
Loading…
Reference in New Issue
Block a user