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

Files at this revision

API Documentation at this revision

Comitter:
Jerome Coutant
Date:
Thu Nov 07 11:33:58 2019 +0100
Commit message:
First commit

Changed in this revision

.hgignore Show annotated file Show diff for this revision Revisions of this file
BSP_DISCO_H747I.lib Show annotated file Show diff for this revision Revisions of this file
TOOLCHAIN_ARM_STD/stm32h747xI.sct Show annotated file Show diff for this revision Revisions of this file
TOOLCHAIN_GCC_ARM/STM32H747xI.ld Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-os.lib Show annotated file Show diff for this revision Revisions of this file
--- /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