2018-04-28 05:12 PM
Hi, trying to get I2S working with 24 bit data. The function call HAL_I2S_Transmit takes a pointer to unsigned 16 bit var so there needs to be 2 transfers to get 24 bits into the I2S. I am using an unsigned 32 bit var and putting the 24 bit value into it, left justified. When the HAL driver unpacks the 32 bit data it does so backwards. Example:
thisData = 0x12345678;
uint16_t *pData = (uint16_t *) &thisData; uint16_t data1 = (*pData++); uint16_t data2 = (*pData++);data1 gets the lower 16 bits: 0x5678
data2 gets the upper 16 bits: 0x1234I need to take a 24 bit number and put it into a 32 bit variable, left justified, and send a 16 bit pointer to the HAL I2S function. How do I do this? What am I missing?
Thanks!
#endianness2018-04-28 05:59 PM
You have a 32bit value and you are reading the first half, then the second half.
We all like Big Indians, it use to be these processors had an option to switch Indians,
but its not supported by the DMA hardware
In the RM0090 reference manual, it shows this:
2.2 Memory organization
The bytes are coded in memory in little endian format. The lowest numbered byte in a word
is considered the word’s least significant byte and the highest numbered byte, the word’smost significant.10.3.10 Programmable data width, packing/unpacking, endianess
The DMA controller only copes with little-endian addressing for both source and
destination. This is described in Table 46: Packing/unpacking & endian behavior (bitPINC = MINC = 1).Change the type ...
I use a Union operator.
union cacheDataConverter { // 8bit to 64bit converter
uint64_t d64[1]; uint32_t d32[2]; uint16_t d16[4]; uint8_t d8[8]; // byte data read/write buffer char string[8];};in your case:
I would use a 32bit pointer:
cacheDataConverter cacheData;
uint32_t *pData = (uint32_t *) &thisDataTable;
.
.
cacheData.d32[0] = *pData++;
data1 = cacheData.d16[1];
data2 = cacheData.d16[0];
2018-06-10 03:25 AM
First, you example value 0x12345678 does not fit into 24-bits. Second, you have to change the byte order according to the section 'I2S Philips standard' of the Reference Manual (section 28.4.3.) and the example in the same section.
2018-06-10 04:22 AM
Lots of ways to do it. Like left shift it to a 32 bit type first and use the code pieces you posted earlier.
Or a union......
2018-06-10 05:59 PM
You could use the Assembler REV instruction. this will reverse your data in one cycle.
excerpt from
Turvey.Clive.002
/**
\brief Reverse byte order (32 bit) \details Reverses the byte order in integer value. \param [in] value Value to reverse \return Reversed value */ #define __REV __rev/**
\brief Reverse byte order (16 bit) \details Reverses the byte order in two unsigned short values. \param [in] value Value to reverse \return Reversed value */ #ifndef __NO_EMBEDDED_ASM __attribute__((section('.rev16_text'))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value) { rev16 r0, r0 bx lr } #endif/**
\brief Reverse byte order in signed short value \details Reverses the byte order in a signed short value with sign extension to integer. \param [in] value Value to reverse \return Reversed value */ #ifndef __NO_EMBEDDED_ASM __attribute__((section('.revsh_text'))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value) { revsh r0, r0 bx lr } #endif2018-06-10 06:45 PM
'
You could use the Assembler REV instruction. this will reverse your data in one cycle.'
no point in doing it yourself - it is part of cmsis.
anyway, the OP's ask is not about reversing the order but fast-packing / unpacking a 24-bit type to 16-bit types.