I can't build the i2s example code. If I change in i2s.h:
typedef struct {
i2s_mode_t mode; /*!< I2S work mode*/
int sample_rate; /*!< I2S sample rate*/
i2s_bits_per_sample_t bits_per_sample; /*!< I2S bits per sample*/
i2s_channel_fmt_t channel_format; /*!< I2S channel format */
i2s_comm_format_t communication_format; /*!< I2S communication format */
int intr_alloc_flags; /*!< Flags used to allocate the interrupt. One or multiple (ORred) ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info */
int dma_buf_count; /*!< I2S DMA Buffer Count */
int dma_buf_len; /*!< I2S DMA Buffer Length */
} i2s_config_t;
i2s_mode_t and i2s_comm_format_t to int. Then it builds and works.
Board: ESP32 Dev Module
Core Installation/update date: 12/Sep/2017
IDE name: Arduino IDE 1.8.3
Describe your problem here
#include "driver/i2s.h"
static const i2s_config_t i2s_config = {
.mode = I2S_MODE_MASTER | I2S_MODE_TX,
.sample_rate = 48000,
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //I2S_CHANNEL_FMT_RIGHT_LEFT,
.communication_format = I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, // high interrupt priority
.dma_buf_count = 6,
.dma_buf_len = 512
};
void setup() {
}
void loop() {
}
"C:\Users\jpmendoza\Documents\Arduino\hardware\espressif\esp32/tools/xtensa-esp32-elf/bin/xtensa-esp32-elf-g++" -DESP_PLATFORM -DMBEDTLS_CONFIG_FILE="mbedtls/esp_config.h" -DHAVE_CONFIG_H "-IC:\Users\jpmendoza\Documents\Arduino\hardware\espressif\esp32/tools/sdk/include/config" "-IC:\Users\jpmendoza\Documents\Arduino\hardware\espressif\esp32/tools/sdk/include/bluedroid" "-IC:\Users\jpmendoza\Documents\Arduino\hardware\espressif\esp32/tools/sdk/include/app_trace" "-IC:\Users\jpmendoza\Documents\Arduino\hardware\espressif\esp32/tools/sdk/include/app_update" "-IC:\Users\jpmendoza\Documents\Arduino\hardware\espressif\esp32/tools/sdk/include/bootloader_support" "-IC:\Users\jpmendoza\Documents\Arduino\hardware\espressif\esp32/tools/sdk/include/bt" "-IC:\Users\jpmendoza\Documents\Arduino\hardware\espressif\esp32/tools/sdk/include/driver" "-IC:\Users\jpmendoza\Documents\Arduino\hardware\espressif\esp32/tools/sdk/include/esp32" "-IC:\Users\jpmendoza\Documents\Arduino\hardware\espressif\esp32/tools/sdk/include/ethernet" "-IC:\Users\jpmendoza\Documents\Arduino\hardware\espressif\esp32/tools/sdk/include/fatfs" "-IC:\Users\jpmendoza\Documents\Arduino\hardware\espressif\esp32/tools/sdk/include/freertos" "-IC:\Users\jpmendoza\Documents\Arduino\hardware\espressif\esp32/tools/sdk/include/heap" "-IC:\Users\jpmendoza\Documents\Arduino\hardware\espressif\esp32/tools/sdk/include/jsmn" "-IC:\Users\jpmendoza\Documents\Arduino\hardware\espressif\esp32/tools/sdk/include/log" "-IC:\Users\jpmendoza\Documents\Arduino\hardware\espressif\esp32/tools/sdk/include/mdns" "-IC:\Users\jpmendoza\Documents\Arduino\hardware\espressif\esp32/tools/sdk/include/mbedtls" "-IC:\Users\jpmendoza\Documents\Arduino\hardware\espressif\esp32/tools/sdk/include/mbedtls_port" "-IC:\Users\jpmendoza\Documents\Arduino\hardware\espressif\esp32/tools/sdk/include/newlib" "-IC:\Users\jpmendoza\Documents\Arduino\hardware\espressif\esp32/tools/sdk/include/nvs_flash" "-IC:\Users\jpmendoza\Documents\Arduino\hardware\espressif\esp32/tools/sdk/include/openssl" "-IC:\Users\jpmendoza\Documents\Arduino\hardware\espressif\esp32/tools/sdk/include/soc" "-IC:\Users\jpmendoza\Documents\Arduino\hardware\espressif\esp32/tools/sdk/include/spi_flash" "-IC:\Users\jpmendoza\Documents\Arduino\hardware\espressif\esp32/tools/sdk/include/sdmmc" "-IC:\Users\jpmendoza\Documents\Arduino\hardware\espressif\esp32/tools/sdk/include/tcpip_adapter" "-IC:\Users\jpmendoza\Documents\Arduino\hardware\espressif\esp32/tools/sdk/include/ulp" "-IC:\Users\jpmendoza\Documents\Arduino\hardware\espressif\esp32/tools/sdk/include/vfs" "-IC:\Users\jpmendoza\Documents\Arduino\hardware\espressif\esp32/tools/sdk/include/wear_levelling" "-IC:\Users\jpmendoza\Documents\Arduino\hardware\espressif\esp32/tools/sdk/include/xtensa-debug-module" "-IC:\Users\jpmendoza\Documents\Arduino\hardware\espressif\esp32/tools/sdk/include/newlib" "-IC:\Users\jpmendoza\Documents\Arduino\hardware\espressif\esp32/tools/sdk/include/coap" "-IC:\Users\jpmendoza\Documents\Arduino\hardware\espressif\esp32/tools/sdk/include/wpa_supplicant" "-IC:\Users\jpmendoza\Documents\Arduino\hardware\espressif\esp32/tools/sdk/include/expat" "-IC:\Users\jpmendoza\Documents\Arduino\hardware\espressif\esp32/tools/sdk/include/json" "-IC:\Users\jpmendoza\Documents\Arduino\hardware\espressif\esp32/tools/sdk/include/nghttp" "-IC:\Users\jpmendoza\Documents\Arduino\hardware\espressif\esp32/tools/sdk/include/lwip" -std=gnu++11 -fno-exceptions -fno-rtti -Os -g3 -Wpointer-arith -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -mlongcalls -nostdlib -Wall -Werror=all -Wno-error=unused-function -Wno-error=unused-but-set-variable -Wno-error=unused-variable -Wno-error=deprecated-declarations -Wno-unused-parameter -Wno-sign-compare -fno-rtti -MMD -c -DF_CPU=240000000L -DARDUINO=10803 -DARDUINO_ESP32_DEV -DARDUINO_ARCH_ESP32 -DESP32 -DCORE_DEBUG_LEVEL=0 "-IC:\Users\jpmendoza\Documents\Arduino\hardware\espressif\esp32\cores\esp32" "-IC:\Users\jpmendoza\Documents\Arduino\hardware\espressif\esp32\variants\esp32" "-IC:\Users\jpmendoza\Documents\Arduino\libraries\SGTL5000" "-IC:\Users\jpmendoza\Documents\Arduino\hardware\espressif\esp32\libraries\Wire\src" "C:\Users\JPMEND~1\AppData\Local\Temp\arduino_build_937948\sketch\SDMMC_Test.ino.cpp" -o "C:\Users\JPMEND~1\AppData\Local\Temp\arduino_build_937948\sketch\SDMMC_Test.ino.cpp.o"
SDMMC_Test:37: error: invalid conversion from 'int' to 'i2s_mode_t' [-fpermissive]
};
^
SDMMC_Test:37: error: invalid conversion from 'int' to 'i2s_comm_format_t' [-fpermissive]
exit status 1
invalid conversion from 'int' to 'i2s_mode_t' [-fpermissive]
I had the "i2s_mode_t" and "i2s_port_t" with this error too (using VS Code). The reason is the same for both - strict typing.
The "i2s_port_t" is caused by the definition in the Espressif reference example:
static const i2s_port_t i2s_num = 0; // i2s port number
Which is fixed by using the enumerated type (i2s_port_t) for port 0:
static const i2s_port_t i2s_num = I2S_NUM_0; // i2s port number
Mode is defined as an enum within the "i2s_config_t" structure and it will only compile, as is, with the permissive flag. Unless this flag is set one cannot combine the mode flags into a bit-field (hence the "int" which is the result of ORing multiple enums).
Either the mode field of "i2s_config_t should be an uint type to take a bit-field or one should only use one enumerated option. [I consider using fpermissive as an anti-pattern.]
@riataman did you try the extern C thing?
I did and it failed with the same error. A standard c cast (.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX)), didn't work either.
What worked at the end was this:
static const i2s_config_t i2s_config = {
.mode = static_cast<i2s_mode_t>(I2S_MODE_MASTER | I2S_MODE_TX),
.sample_rate = 44100,
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
.communication_format = static_cast<i2s_comm_format_t>(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB),
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, // high interrupt priority
.dma_buf_count = 3,
.dma_buf_len = 512
};
.mode = static_cast
(I2S_MODE_MASTER | I2S_MODE_TX),
That equates to 5 which is not a valid (unscoped) enumeration (can be 1,2,4,8.16 or 64)
.communication_format = static_cast
(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB),
That equates to 3 which is also not a valid (unscoped) enumeration (can be 1,2,4,8,16 or 32)
Casting rules
Unscoped enum constants can be implicitly converted to int, but an int is never implicitly convertible to an enum value.
As you have shown, it must be explicitly cast to circumvent the typing system. This should not be required and is a code smell.
Until the issue is fixed, i use following template:
template<typename Enum>
Enum operator |(Enum lhs, Enum rhs)
{
return static_cast<Enum> (lhs | rhs);
}
This way i can use the code from esp32 example as it is:
static const i2s_config_t i2s_config = {
.mode = I2S_MODE_MASTER | I2S_MODE_TX,
.sample_rate = 44100,
.bits_per_sample = 16,
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
.communication_format = I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB,
.intr_alloc_flags = 0, // default interrupt priority
.dma_buf_count = 8,
.dma_buf_len = 64,
.use_apll = false
};
This example code from espidf cannot be plain copied to C++ code.
I solved this by copying the example code in a separate .c file (accompanied with a .h file) and declared a function in the .c file which does the talking to i2s.
This is an ancient, abandoned issue. There is now an example that demonstrates how to cast the field.
Tnx @lbernstone !!
However, how would one know that the well maintained repository https://github.com/espressif/esp-idf (which is recommended framework?!) contains examples that are 'not suitable for the job' ? Or am I confused about what the recommended framework is for ESP32 programming? Thought that Arduino framework was kinda 'nahh' ?
The examples in that repository work fine. They will not work with arduino; many are straight up incompatible with C++ without significant modifications.
The esp-idf framework is an official framework supported by espressif staff, for use with gcc. arduino-esp32 is community supported (with a lot of help from a single espressif employee).
This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. Thank you for your contributions.
[STALE_DEL] This stale issue has been automatically closed. Thank you for your contributions.
Most helpful comment
That equates to 5 which is not a valid (unscoped) enumeration (can be 1,2,4,8.16 or 64)
That equates to 3 which is also not a valid (unscoped) enumeration (can be 1,2,4,8,16 or 32)
source
As you have shown, it must be explicitly cast to circumvent the typing system. This should not be required and is a code smell.