Manage RMT channel resources with alloc()/release().

This commit is contained in:
devsaurus 2017-04-01 10:08:13 +02:00
parent e33fb81b77
commit e2fdd4adbe
3 changed files with 139 additions and 35 deletions

View File

@ -115,6 +115,30 @@ int platform_i2c_send_byte( unsigned id, uint8_t data, int ack_check_en );
int platform_i2c_recv_byte( unsigned id, int ack_val ); int platform_i2c_recv_byte( unsigned id, int ack_val );
// *****************************************************************************
// RMT platform interface
/**
* @brief Allocate an RMT channel.
*
* @param num_mem Number of memory blocks.
*
* @return
* - Channel number when successful
* - -1 if no channel available
*
*/
int platform_rmt_allocate( uint8_t num_mem );
/**
* @brief Release a previously allocated RMT channel.
*
* @param channel Channel number.
*
*/
void platform_rmt_release( uint8_t channel );
// ***************************************************************************** // *****************************************************************************
// Onewire platform interface // Onewire platform interface

View File

@ -67,6 +67,8 @@ sample code bearing this copyright.
#define TRUE (1==1) #define TRUE (1==1)
#define FALSE !TRUE #define FALSE !TRUE
#undef OW_DEBUG
// ***************************************************************************** // *****************************************************************************
// Onewire platform interface // Onewire platform interface
@ -105,43 +107,60 @@ static const uint8_t owDefaultPower = 0;
static int onewire_rmt_init( uint8_t gpio_num ) static int onewire_rmt_init( uint8_t gpio_num )
{ {
// acquire an RMT module for TX and RX // acquire an RMT module for TX and RX each
rmt_config_t rmt_tx; if ((ow_rmt.tx = platform_rmt_allocate( 1 )) >= 0) {
ow_rmt.tx = RMT_CHANNEL_7; if ((ow_rmt.rx = platform_rmt_allocate( 1 )) >= 0) {
rmt_tx.channel = ow_rmt.tx;
rmt_tx.gpio_num = gpio_num;
rmt_tx.mem_block_num = 1;
rmt_tx.clk_div = 80;
rmt_tx.tx_config.loop_en = false;
rmt_tx.tx_config.carrier_en = false;
rmt_tx.tx_config.idle_level = 1;
rmt_tx.tx_config.idle_output_en = true;
rmt_tx.rmt_mode = RMT_MODE_TX;
if (rmt_config( &rmt_tx ) != ESP_OK)
return PLATFORM_ERR;
if (rmt_driver_install( rmt_tx.channel, 0, 0 ) != ESP_OK)
return PLATFORM_ERR;
rmt_config_t rmt_rx; #ifdef OW_DEBUG
ow_rmt.rx = RMT_CHANNEL_6; ESP_LOGI("ow", "RMT TX channel: %d", ow_rmt.tx);
rmt_rx.channel = ow_rmt.rx; ESP_LOGI("ow", "RMT RX channel: %d", ow_rmt.rx);
rmt_rx.gpio_num = gpio_num; #endif
rmt_rx.clk_div = 80;
rmt_rx.mem_block_num = 1;
rmt_rx.rmt_mode = RMT_MODE_RX;
rmt_rx.rx_config.filter_en = true;
rmt_rx.rx_config.filter_ticks_thresh = 30;
rmt_rx.rx_config.idle_threshold = OW_DURATION_RX_IDLE;
if (rmt_config( &rmt_rx ) != ESP_OK)
return PLATFORM_ERR;
if (rmt_driver_install( rmt_rx.channel, 512, 0 ) != ESP_OK)
return PLATFORM_ERR;
rmt_get_ringbuf_handler( ow_rmt.rx, &ow_rmt.rb ); rmt_config_t rmt_tx;
rmt_tx.channel = ow_rmt.tx;
rmt_tx.gpio_num = gpio_num;
rmt_tx.mem_block_num = 1;
rmt_tx.clk_div = 80;
rmt_tx.tx_config.loop_en = false;
rmt_tx.tx_config.carrier_en = false;
rmt_tx.tx_config.idle_level = 1;
rmt_tx.tx_config.idle_output_en = true;
rmt_tx.rmt_mode = RMT_MODE_TX;
if (rmt_config( &rmt_tx ) == ESP_OK) {
if (rmt_driver_install( rmt_tx.channel, 0, 0 ) == ESP_OK) {
ow_rmt.gpio = gpio_num; rmt_config_t rmt_rx;
rmt_rx.channel = ow_rmt.rx;
rmt_rx.gpio_num = gpio_num;
rmt_rx.clk_div = 80;
rmt_rx.mem_block_num = 1;
rmt_rx.rmt_mode = RMT_MODE_RX;
rmt_rx.rx_config.filter_en = true;
rmt_rx.rx_config.filter_ticks_thresh = 30;
rmt_rx.rx_config.idle_threshold = OW_DURATION_RX_IDLE;
if (rmt_config( &rmt_rx ) == ESP_OK) {
if (rmt_driver_install( rmt_rx.channel, 512, 0 ) == ESP_OK) {
return PLATFORM_OK; rmt_get_ringbuf_handler( ow_rmt.rx, &ow_rmt.rb );
ow_rmt.gpio = gpio_num;
return PLATFORM_OK;
}
}
rmt_driver_uninstall( rmt_tx.channel );
}
}
platform_rmt_release( ow_rmt.rx );
}
platform_rmt_release( ow_rmt.tx );
}
return PLATFORM_ERR;
} }
// flush any pending/spurious traces from the RX channel // flush any pending/spurious traces from the RX channel
@ -223,7 +242,8 @@ int platform_onewire_reset( uint8_t gpio_num, uint8_t *presence )
if (rx_items) { if (rx_items) {
if (rx_size >= 1 * sizeof( rmt_item32_t )) { if (rx_size >= 1 * sizeof( rmt_item32_t )) {
#if 0
#ifdef OW_DEBUG
for (int i = 0; i < rx_size / 4; i++) { for (int i = 0; i < rx_size / 4; i++) {
ESP_LOGI("ow", "level: %d, duration %d", rx_items[i].level0, rx_items[i].duration0); ESP_LOGI("ow", "level: %d, duration %d", rx_items[i].level0, rx_items[i].duration0);
ESP_LOGI("ow", "level: %d, duration %d", rx_items[i].level1, rx_items[i].duration1); ESP_LOGI("ow", "level: %d, duration %d", rx_items[i].level1, rx_items[i].duration1);
@ -366,12 +386,14 @@ static int onewire_read_bits( uint8_t gpio_num, uint8_t *data, uint8_t num )
rmt_item32_t* rx_items = (rmt_item32_t *)xRingbufferReceive( ow_rmt.rb, &rx_size, portMAX_DELAY ); rmt_item32_t* rx_items = (rmt_item32_t *)xRingbufferReceive( ow_rmt.rb, &rx_size, portMAX_DELAY );
if (rx_items) { if (rx_items) {
#if 0
#ifdef OW_DEBUG
for (int i = 0; i < rx_size / 4; i++) { for (int i = 0; i < rx_size / 4; i++) {
ESP_LOGI("ow", "level: %d, duration %d", rx_items[i].level0, rx_items[i].duration0); ESP_LOGI("ow", "level: %d, duration %d", rx_items[i].level0, rx_items[i].duration0);
ESP_LOGI("ow", "level: %d, duration %d", rx_items[i].level1, rx_items[i].duration1); ESP_LOGI("ow", "level: %d, duration %d", rx_items[i].level1, rx_items[i].duration1);
} }
#endif #endif
if (rx_size >= num * sizeof( rmt_item32_t )) { if (rx_size >= num * sizeof( rmt_item32_t )) {
for (int i = 0; i < num; i++) { for (int i = 0; i < num; i++) {
read_data >>= 1; read_data >>= 1;

58
components/platform/rmt.c Normal file
View File

@ -0,0 +1,58 @@
#include "platform.h"
#include <string.h>
#include "driver/rmt.h"
static uint8_t rmt_channel_alloc[RMT_CHANNEL_MAX];
static bool rmt_channel_check( uint8_t channel, uint8_t num_mem )
{
if (num_mem == 0 || channel >= RMT_CHANNEL_MAX) {
// wrong parameter
return false;
} else if (num_mem == 1) {
if (rmt_channel_alloc[channel] == 0)
return true;
else
return false;
}
return rmt_channel_check( channel-1, num_mem-1);
}
int platform_rmt_allocate( uint8_t num_mem )
{
int channel;
uint8_t tag = 1;
for (channel = RMT_CHANNEL_MAX-1; channel >= 0; channel--) {
if (rmt_channel_alloc[channel] == 0) {
if (rmt_channel_check( channel, num_mem )) {
rmt_channel_alloc[channel] = tag++;
if (--num_mem == 0)
break;
}
}
}
if (channel >= 0 && num_mem == 0)
return channel;
else
return -1;
}
void platform_rmt_release( uint8_t channel )
{
for ( ; channel < RMT_CHANNEL_MAX; channel++ ) {
uint8_t tag = rmt_channel_alloc[channel];
rmt_channel_alloc[channel] = 0;
if (tag <= 1)
break;
}
}