AUDIO loopback with DISCO_H747I
Dependencies: BSP_DISCO_H747I
Building
hg clone https://mbed.org/teams/ST/code/DISCO_H747I_AUDIO_demo
cd DISCO_H747I_AUDIO_demo
mbed deploy
mbed compile -m DISCO_H747I -t <GCC_ARM/ARM/IAR> -f
Running
A single printf is done at main start
Audio is recorded from board micro (U21) next to joystick.
Audio output is the jack connector (CN11) (green one).
Warning
Audio configuration is not compatible with Ethernet HW patch
https://os.mbed.com/teams/ST/wiki/DISCO_H747I-modifications-for-Ethernet
Revision 0:78e37c7585e6, committed 2019-11-07
- Comitter:
- Jerome Coutant
- Date:
- Thu Nov 07 11:33:58 2019 +0100
- Commit message:
- First commit
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgignore Thu Nov 07 11:33:58 2019 +0100 @@ -0,0 +1,2 @@ +BUILD +mbed-os/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BSP_DISCO_H747I.lib Thu Nov 07 11:33:58 2019 +0100 @@ -0,0 +1,1 @@ +https://os.mbed.com/teams/ST/code/BSP_DISCO_H747I/#bc403474b366
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TOOLCHAIN_ARM_STD/stm32h747xI.sct Thu Nov 07 11:33:58 2019 +0100 @@ -0,0 +1,57 @@ +#! armcc -E +; Scatter-Loading Description File +;****************************************************************************** +;* @attention +;* +;* Copyright (c) 2018-2019 STMicroelectronics. +;* All rights reserved. +;* +;* This software component is licensed by ST under BSD 3-Clause license, +;* the "License"; You may not use this file except in compliance with the +;* License. You may obtain a copy of the License at: +;* opensource.org/licenses/BSD-3-Clause +;* +;****************************************************************************** + +#if !defined(MBED_APP_START) + #define MBED_APP_START 0x08000000 +#endif + +#if !defined(MBED_APP_SIZE) + #define MBED_APP_SIZE 0x100000 +#endif + +#if !defined(MBED_BOOT_STACK_SIZE) + #define MBED_BOOT_STACK_SIZE 0x400 +#endif + +#define Stack_Size MBED_BOOT_STACK_SIZE + +#define MBED_RAM_START 0x24000000 +#define MBED_RAM_SIZE 0x80000 +#define MBED_VECTTABLE_RAM_START 0x20000000 +#define MBED_VECTTABLE_RAM_SIZE 0x298 +#define MBED_RAM0_START (MBED_RAM_START) +#define MBED_RAM0_SIZE (MBED_RAM_SIZE) + +LR_IROM1 MBED_APP_START MBED_APP_SIZE { ; load region size_region + + ER_IROM1 MBED_APP_START MBED_APP_SIZE { ; load address = execution address + *.o (RESET, +First) + *(InRoot$$Sections) + .ANY (+RO) + } + + RW_IRAM1 (MBED_RAM0_START) (MBED_RAM0_SIZE-Stack_Size) { ; RW data + .ANY (+RW +ZI) + } + + ARM_LIB_STACK (MBED_RAM0_START+MBED_RAM0_SIZE) EMPTY -Stack_Size { ; stack + } + + + RW_IRAM2 0x38000000 0x00010000 { ; RW data + *(.RAM_D3) + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TOOLCHAIN_GCC_ARM/STM32H747xI.ld Thu Nov 07 11:33:58 2019 +0100 @@ -0,0 +1,192 @@ +/* Linker script to configure memory regions. */ +/******************************************************************************* + * @attention + * + * Copyright (c) 2018-2019 STMicroelectronics. + * All rights reserved. + * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +#if !defined(MBED_APP_START) + #define MBED_APP_START 0x08000000 +#endif + +#if !defined(MBED_APP_SIZE) + #define MBED_APP_SIZE 1024K +#endif + +#if !defined(MBED_BOOT_STACK_SIZE) + #define MBED_BOOT_STACK_SIZE 0x400 +#endif + +STACK_SIZE = MBED_BOOT_STACK_SIZE; + +MEMORY +{ + FLASH (rx) : ORIGIN = MBED_APP_START, LENGTH = MBED_APP_SIZE + DTCMRAM (rwx) : ORIGIN = 0x20000298, LENGTH = 128K-0x298 + RAM (xrw) : ORIGIN = 0x24000000, LENGTH = 512K + RAM_D2 (xrw) : ORIGIN = 0x30000000, LENGTH = 288K + RAM_D3 (xrw) : ORIGIN = 0x38000000, LENGTH = 64K + ITCMRAM (xrw) : ORIGIN = 0x00000000, LENGTH = 64K +} + +/* Linker script to place sections and symbol values. Should be used together + * with other linker script that defines memory regions FLASH and RAM. + * It references following symbols, which must be defined in code: + * Reset_Handler : Entry of reset handler + * + * It defines following symbols, which code can use without definition: + * __exidx_start + * __exidx_end + * __etext + * __data_start__ + * __preinit_array_start + * __preinit_array_end + * __init_array_start + * __init_array_end + * __fini_array_start + * __fini_array_end + * __data_end__ + * __bss_start__ + * __bss_end__ + * __end__ + * end + * __HeapLimit + * __StackLimit + * __StackTop + * __stack + * _estack + */ +ENTRY(Reset_Handler) + +SECTIONS +{ + .text : + { + KEEP(*(.isr_vector)) + *(.text*) + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.rodata*) + + KEEP(*(.eh_frame*)) + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + + __etext = .; + _sidata = .; + + .data : AT (__etext) + { + __data_start__ = .; + _sdata = .; + *(vtable) + *(.data*) + + . = ALIGN(8); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(8); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + + . = ALIGN(8); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + KEEP(*(.jcr*)) + . = ALIGN(8); + /* All data end */ + __data_end__ = .; + _edata = .; + + } > RAM + + .bss : + { + . = ALIGN(8); + __bss_start__ = .; + _sbss = .; + *(.bss*) + *(COMMON) + . = ALIGN(8); + __bss_end__ = .; + _ebss = .; + } > RAM + + .heap (COPY): + { + __end__ = .; + end = __end__; + *(.heap*) + . = ORIGIN(RAM) + LENGTH(RAM) - STACK_SIZE; + __HeapLimit = .; + } > RAM + + + /* .stack_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later */ + .stack_dummy (COPY): + { + *(.stack*) + } > RAM + + /* Set stack top to end of RAM, and stack limit move down by + * size of stack_dummy section */ + __StackTop = ORIGIN(RAM) + LENGTH(RAM); + _estack = __StackTop; + __StackLimit = __StackTop - STACK_SIZE; + PROVIDE(__stack = __StackTop); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") + + .RAM_D3 (NOLOAD): + { + *(.RAM_D3) + } >RAM_D3 +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Thu Nov 07 11:33:58 2019 +0100 @@ -0,0 +1,150 @@ +#include "mbed.h" +#include "stm32h747i_discovery.h" +#include "stm32h747i_discovery_audio.h" + +extern "C" { + + /* Audio frequency */ +#define AUDIO_FREQUENCY BSP_AUDIO_FREQUENCY_16K +#define AUDIO_IN_PDM_BUFFER_SIZE (uint32_t)(128*AUDIO_FREQUENCY/16000*DEFAULT_AUDIO_IN_CHANNEL_NBR) + + /* Size of the recorder buffer */ +#define RECORD_BUFFER_SIZE 4096 + + /* Define record Buf at D3SRAM @0x38000000 since the BDMA for SAI4 use only this memory */ +#if defined (TOOLCHAIN_IAR) /* IAR */ + /* No need to update linker script */ +#pragma location=0x38000000 + uint16_t recordPDMBuf[AUDIO_IN_PDM_BUFFER_SIZE]; +#else /* GCC_ARM and ARM */ + /* Linker scripts need to be updated to add RAM_D3 section */ + ALIGN_32BYTES(uint16_t recordPDMBuf[AUDIO_IN_PDM_BUFFER_SIZE]) __attribute__((section(".RAM_D3"))); +#endif + + uint16_t playbackBuf[RECORD_BUFFER_SIZE * 2]; + + /* Pointer to record_data */ + uint32_t playbackPtr; + + extern SAI_HandleTypeDef haudio_out_sai; + extern SAI_HandleTypeDef haudio_in_sai; + + + /** + * @brief This function handles DMA2 Stream 1 interrupt request. + * @param None + * @retval None + */ + void AUDIO_OUT_SAIx_DMAx_IRQHandler(void) + /* DMA2_Stream1_IRQHandler redefinition in BSP_DISCO_H747I/STM32H747I-Discovery/stm32h747i_discovery_audio.h */ + { + HAL_DMA_IRQHandler(haudio_out_sai.hdmatx); + } + + + /** + * @brief This function handles BDMA Channel 1 for SAI_PDM interrupt request. + * @param None + * @retval None + */ + void AUDIO_IN_SAI_PDMx_DMAx_IRQHandler(void) + /* BDMA_Channel1_IRQHandler redefinition in BSP_DISCO_H747I/STM32H747I-Discovery/stm32h747i_discovery_audio.h */ + { + HAL_DMA_IRQHandler(haudio_in_sai.hdmarx); + } + + + /** + * @brief Calculates the remaining file size and new position of the pointer. + * @param None + * @retval None + */ + void BSP_AUDIO_IN_TransferComplete_CallBack(void) + /* weak empty function in BSP_DISCO_H747I/STM32H747I-Discovery/stm32h747i_discovery_audio.c */ + { + if (BSP_AUDIO_IN_GetInterface() == AUDIO_IN_INTERFACE_PDM) { + /* Invalidate Data Cache to get the updated content of the SRAM*/ + SCB_InvalidateDCache_by_Addr((uint32_t *)&recordPDMBuf[AUDIO_IN_PDM_BUFFER_SIZE / 2], AUDIO_IN_PDM_BUFFER_SIZE * 2); + + BSP_AUDIO_IN_PDMToPCM((uint16_t *)&recordPDMBuf[AUDIO_IN_PDM_BUFFER_SIZE / 2], &playbackBuf[playbackPtr]); + + /* Clean Data Cache to update the content of the SRAM */ + SCB_CleanDCache_by_Addr((uint32_t *)&playbackBuf[playbackPtr], AUDIO_IN_PDM_BUFFER_SIZE / 4); + + playbackPtr += AUDIO_IN_PDM_BUFFER_SIZE / 4 / 2; + if (playbackPtr >= RECORD_BUFFER_SIZE) { + playbackPtr = 0; + } + } + } + + + /** + * @brief Manages the DMA Half Transfer complete interrupt. + * @param None + * @retval None + */ + void BSP_AUDIO_IN_HalfTransfer_CallBack(void) + /* weak empty function in BSP_DISCO_H747I/STM32H747I-Discovery/stm32h747i_discovery_audio.c */ + { + if (BSP_AUDIO_IN_GetInterface() == AUDIO_IN_INTERFACE_PDM) { + /* Invalidate Data Cache to get the updated content of the SRAM*/ + SCB_InvalidateDCache_by_Addr((uint32_t *)&recordPDMBuf[0], AUDIO_IN_PDM_BUFFER_SIZE * 2); + + BSP_AUDIO_IN_PDMToPCM((uint16_t *)&recordPDMBuf[0], &playbackBuf[playbackPtr]); + + /* Clean Data Cache to update the content of the SRAM */ + SCB_CleanDCache_by_Addr((uint32_t *)&playbackBuf[playbackPtr], AUDIO_IN_PDM_BUFFER_SIZE / 4); + + playbackPtr += AUDIO_IN_PDM_BUFFER_SIZE / 4 / 2; + if (playbackPtr >= RECORD_BUFFER_SIZE) { + playbackPtr = 0; + } + } + } + + + /** + * @brief Audio IN Error callback function + * @param None + * @retval None + */ + void BSP_AUDIO_IN_Error_CallBack(void) + /* weak empty function in BSP_DISCO_H747I/STM32H747I-Discovery/stm32h747i_discovery_audio.c */ + { + MBED_ASSERT(0); + } + +} // extern C + + +int main() +{ + printf("\n\nAUDIO LOOPBACK EXAMPLE WITH AUDIO PDM FOR DISCO-H747I\n"); + + /* Set audio input interface */ + BSP_AUDIO_IN_SelectInterface(AUDIO_IN_INTERFACE_PDM); + + /* Initialize audio IN at REC_FREQ*/ + if (BSP_AUDIO_IN_InitEx(INPUT_DEVICE_DIGITAL_MIC, AUDIO_FREQUENCY, DEFAULT_AUDIO_IN_BIT_RESOLUTION, DEFAULT_AUDIO_IN_CHANNEL_NBR) != AUDIO_OK) { + /* Record Error */ + MBED_ASSERT(0); + } + + /* Initialize audio OUT at REC_FREQ*/ + if (BSP_AUDIO_OUT_Init(OUTPUT_DEVICE_HEADPHONE, 50, AUDIO_FREQUENCY) != AUDIO_OK) { + /* Record Error */ + MBED_ASSERT(0); + } + + /* Set audio slot */ + BSP_AUDIO_OUT_SetAudioFrameSlot(CODEC_AUDIOFRAME_SLOT_02); + + /* Start the record */ + BSP_AUDIO_IN_Record((uint16_t *)recordPDMBuf, AUDIO_IN_PDM_BUFFER_SIZE); + + wait_us(1000); // 1 ms + + /* Start audio output */ + BSP_AUDIO_OUT_Play((uint16_t *)playbackBuf, RECORD_BUFFER_SIZE * 2); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed-os.lib Thu Nov 07 11:33:58 2019 +0100 @@ -0,0 +1,1 @@ +https://github.com/ARMmbed/mbed-os/#3254ec3caea751f05025569c2a16246940875def