From 2f60747dd3b51321903de9c51789765d41ed83e4 Mon Sep 17 00:00:00 2001 From: ozpv <39195175+ozpv@users.noreply.github.com> Date: Mon, 17 Aug 2026 00:01:22 -0500 Subject: audio driver --- Core/Inc/cs4272.h | 35 ++++++++++++++ Core/Inc/dma.h | 52 ++++++++++++++++++++ Core/Inc/stm32h7xx_it.h | 2 + Core/Src/cs4272.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++++ Core/Src/dma.c | 58 ++++++++++++++++++++++ Core/Src/i2c.c | 12 ++++- Core/Src/main.c | 48 +++++++++++++----- Core/Src/sai.c | 54 +++++++++++++++++++-- Core/Src/stm32h7xx_it.c | 30 ++++++++++++ README.md | 4 +- STM32H750ZBTX_FLASH.ld | 10 ++++ audio.ioc | 109 +++++++++++++++++++++++++++++++++-------- 12 files changed, 500 insertions(+), 40 deletions(-) create mode 100755 Core/Inc/cs4272.h create mode 100755 Core/Inc/dma.h create mode 100755 Core/Src/cs4272.c create mode 100755 Core/Src/dma.c diff --git a/Core/Inc/cs4272.h b/Core/Inc/cs4272.h new file mode 100755 index 0000000..30e493a --- /dev/null +++ b/Core/Inc/cs4272.h @@ -0,0 +1,35 @@ +/* + * cs4272.h + * + * Created on: Aug 16, 2026 + * Author: ozpv + */ + +#ifndef INC_CS4272_H_ +#define INC_CS4272_H_ + +// cs4272k-czzr 7. REGISTER QUICK REFERENCE +#define MODE_CONTROL_1 0x01 +#define DAC_CONTROL 0x02 +#define DAC_VOLUME_AND_MIXING_CONTROL 0x03 +#define DAC_CH_A_VOLUME_CONTROL 0x04 +#define DAC_CH_B_VOLUME_CONTROL 0x05 +#define ADC_CONTROL 0x06 +#define MODE_CONTROL_2 0x07 +#define CHIP_ID 0x08 + +#define CS4272_CHIP_ID 0x0 + +// set by ncs/ad0 pin +#define CS4272_I2C_ADDR (0b0010000 << 1) + +#define BUFFER_SIZE 512 + +extern volatile int32_t rx_buffer[BUFFER_SIZE]; +extern volatile int32_t tx_buffer[BUFFER_SIZE]; + +extern const uint8_t CS4272_CONFIG[7]; + +uint8_t CS4272_Init(); + +#endif /* INC_CS4272_H_ */ diff --git a/Core/Inc/dma.h b/Core/Inc/dma.h new file mode 100755 index 0000000..cbf3957 --- /dev/null +++ b/Core/Inc/dma.h @@ -0,0 +1,52 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file dma.h + * @brief This file contains all the function prototypes for + * the dma.c file + ****************************************************************************** + * @attention + * + * Copyright (c) 2026 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __DMA_H__ +#define __DMA_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "main.h" + +/* DMA memory to memory transfer handles -------------------------------------*/ + +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* USER CODE BEGIN Private defines */ + +/* USER CODE END Private defines */ + +void MX_DMA_Init(void); + +/* USER CODE BEGIN Prototypes */ + +/* USER CODE END Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif /* __DMA_H__ */ + diff --git a/Core/Inc/stm32h7xx_it.h b/Core/Inc/stm32h7xx_it.h index b176787..c630d61 100755 --- a/Core/Inc/stm32h7xx_it.h +++ b/Core/Inc/stm32h7xx_it.h @@ -55,6 +55,8 @@ void SVC_Handler(void); void DebugMon_Handler(void); void PendSV_Handler(void); void SysTick_Handler(void); +void DMA1_Stream0_IRQHandler(void); +void DMA1_Stream1_IRQHandler(void); void OTG_HS_EP1_OUT_IRQHandler(void); void OTG_HS_EP1_IN_IRQHandler(void); void OTG_HS_IRQHandler(void); diff --git a/Core/Src/cs4272.c b/Core/Src/cs4272.c new file mode 100755 index 0000000..e7b639e --- /dev/null +++ b/Core/Src/cs4272.c @@ -0,0 +1,126 @@ +/* + * cs4272.c + * + * Created on: Aug 16, 2026 + * Author: ozpv + */ + +#include "i2c.h" +#include "cs4272.h" + +volatile int32_t rx_buffer[BUFFER_SIZE] __attribute__((section(".audio_buffers"))); +volatile int32_t tx_buffer[BUFFER_SIZE] __attribute__((section(".audio_buffers"))); + +const uint8_t CS4272_CONFIG[7] = { + // MODE CONTROL 1 + // single speed i2s slave + 0b00000001, + // DAC CONTROL + // no auto mute steep roll off interpolation 48 kHz de-emphasis + // Soft Ramp Up and Down and no polarity flipping + 0b00001100, + // DAC Volume & Mixing Control + // Channel B Volume = Channel A Volume Soft Ramp and Zero Cross + // a = L b = R + 0b01111001, + // Channel A volume + // 0 dB + // Binary Code Decimal Value Volume Setting + // 0000000 0 0 dB + // 0010100 20 -20 dB + // 0101000 40 -40 dB + // 0111100 60 -60 dB + // 1011010 90 -90 dB + 0b00000000, + // Channel B volume + 0b00000000, + // ADC control + // I2S up to 24-bit data High Pass filter on + // bits 3:2 adc channel mute + 0b00010000, + // MODE CONTROL 2 + // power down OFF + 0b00000010, +}; + +HAL_StatusTypeDef CS4272_ReadRegister(uint8_t addr, uint8_t *data) { + return HAL_I2C_Mem_Read(&hi2c4, CS4272_I2C_ADDR, addr, I2C_MEMADD_SIZE_8BIT, + data, 1, HAL_MAX_DELAY); +} + +HAL_StatusTypeDef CS4272_WriteRegister(uint8_t addr, uint8_t data) { + return HAL_I2C_Mem_Write(&hi2c4, CS4272_I2C_ADDR, addr, + I2C_MEMADD_SIZE_8BIT, &data, 1, HAL_MAX_DELAY); +} + +void CS4272_Reset() { + HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET); + + HAL_Delay(10); + + HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_SET); + + HAL_Delay(10); +} + +uint8_t CS4272_Init() { + CS4272_Reset(); + + if (HAL_I2C_IsDeviceReady(&hi2c4, CS4272_I2C_ADDR, 3, 1000) != HAL_OK) { + return HAL_ERROR; + } + + // 5.2.1 Recommended Power-Up Sequence + // power down mode and control port enable + if (CS4272_WriteRegister(MODE_CONTROL_2, 0x03) != HAL_OK) { + return HAL_ERROR; + } + + // check if device ID is correct + uint8_t id = 0; + if (CS4272_ReadRegister(CHIP_ID, &id) != HAL_OK) { + return HAL_ERROR; + } + + if ((id >> 4) != CS4272_CHIP_ID) { + return 2; + } + + // Configure + uint8_t cfg = 0; + for (uint8_t i = MODE_CONTROL_1; i < MODE_CONTROL_2; ++i) { + if (CS4272_WriteRegister(i, CS4272_CONFIG[i - 1]) != HAL_OK) { + return HAL_ERROR; + } + + if (CS4272_ReadRegister(i, &cfg) != HAL_OK) { + return HAL_ERROR; + } + + if (cfg != CS4272_CONFIG[i - 1]) { + return 2; + } + } + + if (CS4272_WriteRegister(MODE_CONTROL_2, 0x02) != HAL_OK) { + return HAL_ERROR; + } + + if (CS4272_ReadRegister(MODE_CONTROL_2, &cfg) != HAL_OK || cfg != 0x02) { + return 2; + } + + return HAL_OK; +} + +void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai) { + for(int i = 0; i < BUFFER_SIZE / 2; i++) { + tx_buffer[i] = rx_buffer[i]; + } +} + +void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai) { + for(int i = BUFFER_SIZE / 2; i < BUFFER_SIZE; i++) { + tx_buffer[i] = rx_buffer[i]; + } +} diff --git a/Core/Src/dma.c b/Core/Src/dma.c new file mode 100755 index 0000000..86e2fa4 --- /dev/null +++ b/Core/Src/dma.c @@ -0,0 +1,58 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file dma.c + * @brief This file provides code for the configuration + * of all the requested memory to memory DMA transfers. + ****************************************************************************** + * @attention + * + * Copyright (c) 2026 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Includes ------------------------------------------------------------------*/ +#include "dma.h" + +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/*----------------------------------------------------------------------------*/ +/* Configure DMA */ +/*----------------------------------------------------------------------------*/ + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ + +/** + * Enable DMA controller clock + */ +void MX_DMA_Init(void) +{ + + /* DMA controller clock enable */ + __HAL_RCC_DMA1_CLK_ENABLE(); + + /* DMA interrupt init */ + /* DMA1_Stream0_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn); + /* DMA1_Stream1_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn); + +} + +/* USER CODE BEGIN 2 */ + +/* USER CODE END 2 */ + diff --git a/Core/Src/i2c.c b/Core/Src/i2c.c index 6ebfe13..4f3b697 100755 --- a/Core/Src/i2c.c +++ b/Core/Src/i2c.c @@ -38,7 +38,7 @@ void MX_I2C4_Init(void) /* USER CODE END I2C4_Init 1 */ hi2c4.Instance = I2C4; - hi2c4.Init.Timing = 0x00201E2D; + hi2c4.Init.Timing = 0x307075B1; hi2c4.Init.OwnAddress1 = 0; hi2c4.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; hi2c4.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; @@ -74,12 +74,22 @@ void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle) { GPIO_InitTypeDef GPIO_InitStruct = {0}; + RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0}; if(i2cHandle->Instance==I2C4) { /* USER CODE BEGIN I2C4_MspInit 0 */ /* USER CODE END I2C4_MspInit 0 */ + /** Initializes the peripherals clock + */ + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2C4; + PeriphClkInitStruct.I2c4ClockSelection = RCC_I2C4CLKSOURCE_D3PCLK1; + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) + { + Error_Handler(); + } + __HAL_RCC_GPIOB_CLK_ENABLE(); /**I2C4 GPIO Configuration PB8 ------> I2C4_SCL diff --git a/Core/Src/main.c b/Core/Src/main.c index 721e51c..574bba8 100755 --- a/Core/Src/main.c +++ b/Core/Src/main.c @@ -18,6 +18,7 @@ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.h" +#include "dma.h" #include "i2c.h" #include "quadspi.h" #include "sai.h" @@ -27,7 +28,7 @@ /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ - +#include "cs4272.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ @@ -102,7 +103,7 @@ int main(void) SystemClock_Config(); /* Configure the peripherals common clocks */ -// PeriphCommonClock_Config(); + PeriphCommonClock_Config(); /* USER CODE BEGIN SysInit */ @@ -110,13 +111,31 @@ int main(void) /* Initialize all configured peripherals */ MX_GPIO_Init(); + MX_DMA_Init(); MX_FMC_Init(); MX_I2C4_Init(); MX_SAI1_Init(); MX_USB_DEVICE_Init(); -// MX_QUADSPI_Init(); + //MX_QUADSPI_Init(); /* USER CODE BEGIN 2 */ + __HAL_RCC_SAI1_CLK_ENABLE(); + __HAL_SAI_ENABLE(&hsai_BlockA1); + + HAL_Delay(10); + + if (CS4272_Init() != HAL_OK) { + Error_Handler(); + } + + if (HAL_SAI_Receive_DMA(&hsai_BlockB1, (uint8_t *)rx_buffer, BUFFER_SIZE) != HAL_OK) { + Error_Handler(); + } + + if (HAL_SAI_Transmit_DMA(&hsai_BlockA1, (uint8_t *)tx_buffer, BUFFER_SIZE) != HAL_OK) { + Error_Handler(); + } + /* USER CODE END 2 */ /* Infinite loop */ @@ -126,13 +145,6 @@ int main(void) /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ - HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, GPIO_PIN_SET); - - HAL_Delay(1000); - - HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, GPIO_PIN_RESET); - - HAL_Delay(1000); } /* USER CODE END 3 */ } @@ -205,7 +217,7 @@ void PeriphCommonClock_Config(void) /** Initializes the peripherals clock */ - PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2C4|RCC_PERIPHCLK_SAI1; + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SAI1; PeriphClkInitStruct.PLL3.PLL3M = 5; PeriphClkInitStruct.PLL3.PLL3N = 49; PeriphClkInitStruct.PLL3.PLL3P = 20; @@ -215,7 +227,6 @@ void PeriphCommonClock_Config(void) PeriphClkInitStruct.PLL3.PLL3VCOSEL = RCC_PLL3VCOWIDE; PeriphClkInitStruct.PLL3.PLL3FRACN = 1246; PeriphClkInitStruct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLL3; - PeriphClkInitStruct.I2c4ClockSelection = RCC_I2C4CLKSOURCE_PLL3; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { Error_Handler(); @@ -249,9 +260,21 @@ void MPU_Config(void) MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE; MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE; + HAL_MPU_ConfigRegion(&MPU_InitStruct); + + /** Initializes and configures the Region and the memory to be protected + */ + MPU_InitStruct.Number = MPU_REGION_NUMBER1; + MPU_InitStruct.BaseAddress = 0x24000000 ; + MPU_InitStruct.Size = MPU_REGION_SIZE_512KB; + MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE; + MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; + MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE; + HAL_MPU_ConfigRegion(&MPU_InitStruct); /* Enables the MPU */ HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT); + } /** @@ -262,7 +285,6 @@ void Error_Handler(void) { /* USER CODE BEGIN Error_Handler_Debug */ /* User can add his own implementation to report the HAL error return state */ - __disable_irq(); while (1) { } diff --git a/Core/Src/sai.c b/Core/Src/sai.c index 9bd58d9..9601fc8 100755 --- a/Core/Src/sai.c +++ b/Core/Src/sai.c @@ -27,6 +27,8 @@ SAI_HandleTypeDef hsai_BlockA1; SAI_HandleTypeDef hsai_BlockB1; +DMA_HandleTypeDef hdma_sai1_b; +DMA_HandleTypeDef hdma_sai1_a; /* SAI1 init function */ void MX_SAI1_Init(void) @@ -51,7 +53,7 @@ void MX_SAI1_Init(void) hsai_BlockA1.Init.NoDivider = SAI_MCK_OVERSAMPLING_DISABLE; hsai_BlockA1.Init.MckOverSampling = SAI_MCK_OVERSAMPLING_DISABLE; hsai_BlockA1.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_EMPTY; - hsai_BlockA1.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_192K; + hsai_BlockA1.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_48K; hsai_BlockA1.Init.SynchroExt = SAI_SYNCEXT_DISABLE; hsai_BlockA1.Init.MonoStereoMode = SAI_STEREOMODE; hsai_BlockA1.Init.CompandingMode = SAI_NOCOMPANDING; @@ -104,10 +106,31 @@ void HAL_SAI_MspInit(SAI_HandleTypeDef* saiHandle) GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF6_SAI1; HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); + /* Peripheral DMA init*/ + + hdma_sai1_a.Instance = DMA1_Stream1; + hdma_sai1_a.Init.Request = DMA_REQUEST_SAI1_A; + hdma_sai1_a.Init.Direction = DMA_MEMORY_TO_PERIPH; + hdma_sai1_a.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_sai1_a.Init.MemInc = DMA_MINC_ENABLE; + hdma_sai1_a.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; + hdma_sai1_a.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; + hdma_sai1_a.Init.Mode = DMA_CIRCULAR; + hdma_sai1_a.Init.Priority = DMA_PRIORITY_HIGH; + hdma_sai1_a.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + if (HAL_DMA_Init(&hdma_sai1_a) != HAL_OK) + { + Error_Handler(); + } + + /* Several peripheral DMA handle pointers point to the same DMA handle. + Be aware that there is only one channel to perform all the requested DMAs. */ + __HAL_LINKDMA(saiHandle,hdmarx,hdma_sai1_a); + __HAL_LINKDMA(saiHandle,hdmatx,hdma_sai1_a); } if(saiHandle->Instance==SAI1_Block_B) { @@ -124,10 +147,31 @@ void HAL_SAI_MspInit(SAI_HandleTypeDef* saiHandle) GPIO_InitStruct.Pin = GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF6_SAI1; HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); + /* Peripheral DMA init*/ + + hdma_sai1_b.Instance = DMA1_Stream0; + hdma_sai1_b.Init.Request = DMA_REQUEST_SAI1_B; + hdma_sai1_b.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_sai1_b.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_sai1_b.Init.MemInc = DMA_MINC_ENABLE; + hdma_sai1_b.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; + hdma_sai1_b.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; + hdma_sai1_b.Init.Mode = DMA_CIRCULAR; + hdma_sai1_b.Init.Priority = DMA_PRIORITY_HIGH; + hdma_sai1_b.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + if (HAL_DMA_Init(&hdma_sai1_b) != HAL_OK) + { + Error_Handler(); + } + + /* Several peripheral DMA handle pointers point to the same DMA handle. + Be aware that there is only one channel to perform all the requested DMAs. */ + __HAL_LINKDMA(saiHandle,hdmarx,hdma_sai1_b); + __HAL_LINKDMA(saiHandle,hdmatx,hdma_sai1_b); } } @@ -152,6 +196,8 @@ void HAL_SAI_MspDeInit(SAI_HandleTypeDef* saiHandle) */ HAL_GPIO_DeInit(GPIOE, GPIO_PIN_2|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6); + HAL_DMA_DeInit(saiHandle->hdmarx); + HAL_DMA_DeInit(saiHandle->hdmatx); } if(saiHandle->Instance==SAI1_Block_B) { @@ -167,6 +213,8 @@ void HAL_SAI_MspDeInit(SAI_HandleTypeDef* saiHandle) */ HAL_GPIO_DeInit(GPIOE, GPIO_PIN_3); + HAL_DMA_DeInit(saiHandle->hdmarx); + HAL_DMA_DeInit(saiHandle->hdmatx); } } diff --git a/Core/Src/stm32h7xx_it.c b/Core/Src/stm32h7xx_it.c index c4cb071..044e2b2 100755 --- a/Core/Src/stm32h7xx_it.c +++ b/Core/Src/stm32h7xx_it.c @@ -56,6 +56,8 @@ /* External variables --------------------------------------------------------*/ extern PCD_HandleTypeDef hpcd_USB_OTG_HS; +extern DMA_HandleTypeDef hdma_sai1_b; +extern DMA_HandleTypeDef hdma_sai1_a; /* USER CODE BEGIN EV */ /* USER CODE END EV */ @@ -198,6 +200,34 @@ void SysTick_Handler(void) /* please refer to the startup file (startup_stm32h7xx.s). */ /******************************************************************************/ +/** + * @brief This function handles DMA1 stream0 global interrupt. + */ +void DMA1_Stream0_IRQHandler(void) +{ + /* USER CODE BEGIN DMA1_Stream0_IRQn 0 */ + + /* USER CODE END DMA1_Stream0_IRQn 0 */ + HAL_DMA_IRQHandler(&hdma_sai1_b); + /* USER CODE BEGIN DMA1_Stream0_IRQn 1 */ + + /* USER CODE END DMA1_Stream0_IRQn 1 */ +} + +/** + * @brief This function handles DMA1 stream1 global interrupt. + */ +void DMA1_Stream1_IRQHandler(void) +{ + /* USER CODE BEGIN DMA1_Stream1_IRQn 0 */ + + /* USER CODE END DMA1_Stream1_IRQn 0 */ + HAL_DMA_IRQHandler(&hdma_sai1_a); + /* USER CODE BEGIN DMA1_Stream1_IRQn 1 */ + + /* USER CODE END DMA1_Stream1_IRQn 1 */ +} + /** * @brief This function handles USB On The Go HS End Point 1 Out global interrupt. */ diff --git a/README.md b/README.md index 86ddc8a..e225b40 100755 --- a/README.md +++ b/README.md @@ -1,2 +1,2 @@ -Note: Application will not work and get stuck in Reset_Handler with XIP when compiled with no optimization. Ensure you use -Os or -O2. -QUADSPI should not be reinitalized. Only configure it in STM32CubeMX so the clocks are the same and comment out MX_QUADSPI_Init. +Note: Application will not work and get stuck in Reset_Handler with XiP when compiled with no optimization. Ensure you use -Os or -O2. +QUADSPI should not be reinitalized. Only configure it in STM32CubeMX so the clocks are the same and comment out MX_QUADSPI_Init. \ No newline at end of file diff --git a/STM32H750ZBTX_FLASH.ld b/STM32H750ZBTX_FLASH.ld index 9645a88..972ca74 100755 --- a/STM32H750ZBTX_FLASH.ld +++ b/STM32H750ZBTX_FLASH.ld @@ -175,6 +175,16 @@ SECTIONS } .ARM.attributes 0 : { *(.ARM.attributes) } + + .audio_buffers (NOLOAD): + { + . = ALIGN(32); + _saudio_buffers = .; + *(.audio_buffers) + *(.audio_buffers*) + . = ALIGN(32); + _eaudio_buffers = .; + } >RAM_D1 } diff --git a/audio.ioc b/audio.ioc index 4a620ce..68685db 100755 --- a/audio.ioc +++ b/audio.ioc @@ -2,20 +2,65 @@ CAD.formats= CAD.pinconfig= CAD.provider= +CORTEX_M7.AccessPermission_S-Cortex_Memory_Protection_Unit_Region1_Settings_S=MPU_REGION_FULL_ACCESS CORTEX_M7.AccessPermission_Spec=MPU_REGION_FULL_ACCESS +CORTEX_M7.BaseAddress_S-Cortex_Memory_Protection_Unit_Region1_Settings_S=0x24000000 CORTEX_M7.BaseAddress_Spec=0x90000000 CORTEX_M7.CPU_DCache=Enabled CORTEX_M7.CPU_ICache=Enabled +CORTEX_M7.DisableExec_S-Cortex_Memory_Protection_Unit_Region1_Settings_S=MPU_INSTRUCTION_ACCESS_ENABLE CORTEX_M7.DisableExec_Spec=MPU_INSTRUCTION_ACCESS_ENABLE -CORTEX_M7.Enable_S-Cortex_Memory_Protection_Unit_Region1_Settings_S=__NULL -CORTEX_M7.IPParameters=default_mode_Activation,BaseAddress_Spec,Size_Spec,SubRegionDisable_Spec,AccessPermission_Spec,IsShareable_Spec,IsCacheable_Spec,IsBufferable_Spec,CPU_DCache,CPU_ICache,Enable_S-Cortex_Memory_Protection_Unit_Region1_Settings_S,DisableExec_Spec,TypeExtField_Spec +CORTEX_M7.Enable_S-Cortex_Memory_Protection_Unit_Region1_Settings_S=MPU_REGION_ENABLE +CORTEX_M7.IPParameters=default_mode_Activation,BaseAddress_Spec,Size_Spec,SubRegionDisable_Spec,AccessPermission_Spec,IsShareable_Spec,IsCacheable_Spec,IsBufferable_Spec,CPU_DCache,CPU_ICache,Enable_S-Cortex_Memory_Protection_Unit_Region1_Settings_S,DisableExec_Spec,TypeExtField_Spec,BaseAddress_S-Cortex_Memory_Protection_Unit_Region1_Settings_S,Size_S-Cortex_Memory_Protection_Unit_Region1_Settings_S,TypeExtField_S-Cortex_Memory_Protection_Unit_Region1_Settings_S,AccessPermission_S-Cortex_Memory_Protection_Unit_Region1_Settings_S,DisableExec_S-Cortex_Memory_Protection_Unit_Region1_Settings_S,IsShareable_S-Cortex_Memory_Protection_Unit_Region1_Settings_S CORTEX_M7.IsBufferable_Spec=MPU_ACCESS_BUFFERABLE CORTEX_M7.IsCacheable_Spec=MPU_ACCESS_CACHEABLE +CORTEX_M7.IsShareable_S-Cortex_Memory_Protection_Unit_Region1_Settings_S=MPU_ACCESS_SHAREABLE CORTEX_M7.IsShareable_Spec=MPU_ACCESS_NOT_SHAREABLE +CORTEX_M7.Size_S-Cortex_Memory_Protection_Unit_Region1_Settings_S=MPU_REGION_SIZE_512KB CORTEX_M7.Size_Spec=MPU_REGION_SIZE_16MB CORTEX_M7.SubRegionDisable_Spec=0x0 +CORTEX_M7.TypeExtField_S-Cortex_Memory_Protection_Unit_Region1_Settings_S=MPU_TEX_LEVEL1 CORTEX_M7.TypeExtField_Spec=MPU_TEX_LEVEL1 CORTEX_M7.default_mode_Activation=1 +Dma.Request0=SAI1_B +Dma.Request1=SAI1_A +Dma.RequestsNb=2 +Dma.SAI1_A.1.Direction=DMA_MEMORY_TO_PERIPH +Dma.SAI1_A.1.EventEnable=DISABLE +Dma.SAI1_A.1.FIFOMode=DMA_FIFOMODE_DISABLE +Dma.SAI1_A.1.Instance=DMA1_Stream1 +Dma.SAI1_A.1.MemDataAlignment=DMA_MDATAALIGN_WORD +Dma.SAI1_A.1.MemInc=DMA_MINC_ENABLE +Dma.SAI1_A.1.Mode=DMA_CIRCULAR +Dma.SAI1_A.1.PeriphDataAlignment=DMA_PDATAALIGN_WORD +Dma.SAI1_A.1.PeriphInc=DMA_PINC_DISABLE +Dma.SAI1_A.1.Polarity=HAL_DMAMUX_REQ_GEN_RISING +Dma.SAI1_A.1.Priority=DMA_PRIORITY_HIGH +Dma.SAI1_A.1.RequestNumber=1 +Dma.SAI1_A.1.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode,SignalID,Polarity,RequestNumber,SyncSignalID,SyncPolarity,SyncEnable,EventEnable,SyncRequestNumber +Dma.SAI1_A.1.SignalID=NONE +Dma.SAI1_A.1.SyncEnable=DISABLE +Dma.SAI1_A.1.SyncPolarity=HAL_DMAMUX_SYNC_NO_EVENT +Dma.SAI1_A.1.SyncRequestNumber=1 +Dma.SAI1_A.1.SyncSignalID=NONE +Dma.SAI1_B.0.Direction=DMA_PERIPH_TO_MEMORY +Dma.SAI1_B.0.EventEnable=DISABLE +Dma.SAI1_B.0.FIFOMode=DMA_FIFOMODE_DISABLE +Dma.SAI1_B.0.Instance=DMA1_Stream0 +Dma.SAI1_B.0.MemDataAlignment=DMA_MDATAALIGN_WORD +Dma.SAI1_B.0.MemInc=DMA_MINC_ENABLE +Dma.SAI1_B.0.Mode=DMA_CIRCULAR +Dma.SAI1_B.0.PeriphDataAlignment=DMA_PDATAALIGN_WORD +Dma.SAI1_B.0.PeriphInc=DMA_PINC_DISABLE +Dma.SAI1_B.0.Polarity=HAL_DMAMUX_REQ_GEN_RISING +Dma.SAI1_B.0.Priority=DMA_PRIORITY_HIGH +Dma.SAI1_B.0.RequestNumber=1 +Dma.SAI1_B.0.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode,SignalID,Polarity,RequestNumber,SyncSignalID,SyncPolarity,SyncEnable,EventEnable,SyncRequestNumber +Dma.SAI1_B.0.SignalID=NONE +Dma.SAI1_B.0.SyncEnable=DISABLE +Dma.SAI1_B.0.SyncPolarity=HAL_DMAMUX_SYNC_NO_EVENT +Dma.SAI1_B.0.SyncRequestNumber=1 +Dma.SAI1_B.0.SyncSignalID=NONE FMC.CASLatency1=FMC_SDRAM_CAS_LATENCY_2 FMC.ColumnBitsNumber1=FMC_SDRAM_COLUMN_BITS_NUM_9 FMC.ExitSelfRefreshDelay1=12 @@ -33,8 +78,9 @@ FMC.SDClockPeriod2=FMC_SDRAM_CLOCK_PERIOD_2 File.Version=6 GPIO.groupedBy=Group By Peripherals I2C4.I2C_Speed_Mode=I2C_Standard -I2C4.IPParameters=Timing,I2C_Speed_Mode -I2C4.Timing=0x00201E2D +I2C4.IPParameters=I2C_Speed_Mode,Speed,Timing +I2C4.Speed=100 +I2C4.Timing=0x307075B1 KeepUserPlacement=false MMTAppRegionsCount=0 MMTConfigApplied=false @@ -43,17 +89,18 @@ Mcu.CPN=STM32H750ZBT6 Mcu.Family=STM32H7 Mcu.IP0=CORTEX_M7 Mcu.IP1=DEBUG -Mcu.IP10=USB_DEVICE -Mcu.IP11=USB_OTG_HS -Mcu.IP2=FMC -Mcu.IP3=I2C4 -Mcu.IP4=MEMORYMAP -Mcu.IP5=NVIC -Mcu.IP6=QUADSPI -Mcu.IP7=RCC -Mcu.IP8=SAI1 -Mcu.IP9=SYS -Mcu.IPNb=12 +Mcu.IP10=SYS +Mcu.IP11=USB_DEVICE +Mcu.IP12=USB_OTG_HS +Mcu.IP2=DMA +Mcu.IP3=FMC +Mcu.IP4=I2C4 +Mcu.IP5=MEMORYMAP +Mcu.IP6=NVIC +Mcu.IP7=QUADSPI +Mcu.IP8=RCC +Mcu.IP9=SAI1 +Mcu.IPNb=13 Mcu.Name=STM32H750ZBTx Mcu.Package=LQFP144 Mcu.Pin0=PE2 @@ -153,6 +200,8 @@ Mcu.UserName=STM32H750ZBTx MxCube.Version=6.17.0 MxDb.Version=DB.6.0.170 NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false +NVIC.DMA1_Stream0_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true +NVIC.DMA1_Stream1_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false NVIC.ForceEnableDMAVector=true NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false @@ -286,14 +335,29 @@ PE12.Signal=FMC_D9_DA9 PE13.Signal=FMC_D10_DA10 PE14.Signal=FMC_D11_DA11 PE15.Signal=FMC_D12_DA12 +PE2.GPIOParameters=GPIO_Speed,GPIO_Mode +PE2.GPIO_Mode=GPIO_MODE_AF_PP +PE2.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH PE2.Mode=SAI_A_MasterWithClock PE2.Signal=SAI1_MCLK_A +PE3.GPIOParameters=GPIO_Speed,GPIO_Mode +PE3.GPIO_Mode=GPIO_MODE_AF_PP +PE3.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH PE3.Mode=SAI_B_SyncSlave PE3.Signal=SAI1_SD_B +PE4.GPIOParameters=GPIO_Speed,GPIO_Mode +PE4.GPIO_Mode=GPIO_MODE_AF_PP +PE4.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH PE4.Mode=SAI_A_MasterWithClock PE4.Signal=SAI1_FS_A +PE5.GPIOParameters=GPIO_Speed,GPIO_Mode +PE5.GPIO_Mode=GPIO_MODE_AF_PP +PE5.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH PE5.Mode=SAI_A_MasterWithClock PE5.Signal=SAI1_SCK_A +PE6.GPIOParameters=GPIO_Speed,GPIO_Mode +PE6.GPIO_Mode=GPIO_MODE_AF_PP +PE6.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH PE6.Mode=SAI_A_MasterWithClock PE6.Signal=SAI1_SD_A PE7.Signal=FMC_D4_DA4 @@ -368,7 +432,7 @@ ProjectManager.ToolChainLocation= ProjectManager.UAScriptAfterPath= ProjectManager.UAScriptBeforePath= ProjectManager.UnderRoot=true -ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_FMC_Init-FMC-false-HAL-true,4-MX_I2C4_Init-I2C4-false-HAL-true,5-MX_SAI1_Init-SAI1-false-HAL-true,6-MX_USB_DEVICE_Init-USB_DEVICE-false-HAL-false,7-MX_QUADSPI_Init-QUADSPI-false-HAL-true,0-MX_CORTEX_M7_Init-CORTEX_M7-false-HAL-true +ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_DMA_Init-DMA-false-HAL-true,4-MX_FMC_Init-FMC-false-HAL-true,5-MX_I2C4_Init-I2C4-false-HAL-true,6-MX_SAI1_Init-SAI1-false-HAL-true,7-MX_USB_DEVICE_Init-USB_DEVICE-false-HAL-false,8-MX_QUADSPI_Init-QUADSPI-false-HAL-true,0-MX_CORTEX_M7_Init-CORTEX_M7-false-HAL-true QUADSPI.ClockPrescaler=2 QUADSPI.FifoThreshold=4 QUADSPI.FlashSize=23 @@ -423,9 +487,8 @@ RCC.HPRE=RCC_HCLK_DIV2 RCC.HRTIMFreq_Value=240000000 RCC.HSE_VALUE=25000000 RCC.I2C123Freq_Value=120000000 -RCC.I2C4CLockSelection=RCC_I2C4CLKSOURCE_PLL3 -RCC.I2C4Freq_Value=8192016.6015625 -RCC.IPParameters=ADCFreq_Value,AHB12Freq_Value,AHB4Freq_Value,APB1Freq_Value,APB2Freq_Value,APB3Freq_Value,APB4Freq_Value,AXIClockFreq_Value,CECFreq_Value,CKPERFreq_Value,CortexFreq_Value,CpuClockFreq_Value,D1CPREFreq_Value,D1PPRE,D2PPRE1,D2PPRE2,D3PPRE,DFSDMACLkFreq_Value,DFSDMFreq_Value,DIVM1,DIVM2,DIVM3,DIVN1,DIVN2,DIVN3,DIVP1Freq_Value,DIVP2Freq_Value,DIVP3,DIVP3Freq_Value,DIVQ1,DIVQ1Freq_Value,DIVQ2Freq_Value,DIVQ3,DIVQ3Freq_Value,DIVR1Freq_Value,DIVR2,DIVR2Freq_Value,DIVR3,DIVR3Freq_Value,FDCANFreq_Value,FMCCLockSelection,FMCFreq_Value,FamilyName,HCLK3ClockFreq_Value,HCLKFreq_Value,HPRE,HRTIMFreq_Value,HSE_VALUE,I2C123Freq_Value,I2C4CLockSelection,I2C4Freq_Value,LPTIM1Freq_Value,LPTIM2Freq_Value,LPTIM345Freq_Value,LPUART1Freq_Value,LTDCFreq_Value,MCO1PinFreq_Value,MCO2PinFreq_Value,PLL2FRACN,PLL3FRACN,PLLFRACN,QSPICLockSelection,QSPIFreq_Value,RNGFreq_Value,RTCFreq_Value,SAI1CLockSelection,SAI1Freq_Value,SAI23Freq_Value,SAI4AFreq_Value,SAI4BFreq_Value,SDMMCFreq_Value,SPDIFRXFreq_Value,SPI123Freq_Value,SPI45Freq_Value,SPI6Freq_Value,SWPMI1Freq_Value,SYSCLKFreq_VALUE,SYSCLKSource,Tim1OutputFreq_Value,Tim2OutputFreq_Value,TraceFreq_Value,USART16Freq_Value,USART234578Freq_Value,USBFreq_Value,VCO1OutputFreq_Value,VCO2OutputFreq_Value,VCO3OutputFreq_Value,VCOInput1Freq_Value,VCOInput2Freq_Value,VCOInput3Freq_Value +RCC.I2C4Freq_Value=120000000 +RCC.IPParameters=ADCFreq_Value,AHB12Freq_Value,AHB4Freq_Value,APB1Freq_Value,APB2Freq_Value,APB3Freq_Value,APB4Freq_Value,AXIClockFreq_Value,CECFreq_Value,CKPERFreq_Value,CortexFreq_Value,CpuClockFreq_Value,D1CPREFreq_Value,D1PPRE,D2PPRE1,D2PPRE2,D3PPRE,DFSDMACLkFreq_Value,DFSDMFreq_Value,DIVM1,DIVM2,DIVM3,DIVN1,DIVN2,DIVN3,DIVP1Freq_Value,DIVP2Freq_Value,DIVP3,DIVP3Freq_Value,DIVQ1,DIVQ1Freq_Value,DIVQ2Freq_Value,DIVQ3,DIVQ3Freq_Value,DIVR1Freq_Value,DIVR2,DIVR2Freq_Value,DIVR3,DIVR3Freq_Value,FDCANFreq_Value,FMCCLockSelection,FMCFreq_Value,FamilyName,HCLK3ClockFreq_Value,HCLKFreq_Value,HPRE,HRTIMFreq_Value,HSE_VALUE,I2C123Freq_Value,I2C4Freq_Value,LPTIM1Freq_Value,LPTIM2Freq_Value,LPTIM345Freq_Value,LPUART1Freq_Value,LTDCFreq_Value,MCO1PinFreq_Value,MCO2PinFreq_Value,PLL2FRACN,PLL3FRACN,PLLFRACN,QSPICLockSelection,QSPIFreq_Value,RNGFreq_Value,RTCFreq_Value,SAI1CLockSelection,SAI1Freq_Value,SAI23Freq_Value,SAI4AFreq_Value,SAI4BFreq_Value,SDMMCFreq_Value,SPDIFRXFreq_Value,SPI123Freq_Value,SPI45Freq_Value,SPI6Freq_Value,SWPMI1Freq_Value,SYSCLKFreq_VALUE,SYSCLKSource,Tim1OutputFreq_Value,Tim2OutputFreq_Value,TraceFreq_Value,USART16Freq_Value,USART234578Freq_Value,USBFreq_Value,VCO1OutputFreq_Value,VCO2OutputFreq_Value,VCO3OutputFreq_Value,VCOInput1Freq_Value,VCOInput2Freq_Value,VCOInput3Freq_Value RCC.LPTIM1Freq_Value=120000000 RCC.LPTIM2Freq_Value=120000000 RCC.LPTIM345Freq_Value=120000000 @@ -465,16 +528,20 @@ RCC.VCO3OutputFreq_Value=245760498.046875 RCC.VCOInput1Freq_Value=5000000 RCC.VCOInput2Freq_Value=12500000 RCC.VCOInput3Freq_Value=5000000 +SAI1.AudioFrequency-SAI_A_MasterWithClock=SAI_AUDIO_FREQUENCY_48K SAI1.BasicDataSize-SAI_A_MasterWithClock=SAI_PROTOCOL_DATASIZE_24BIT SAI1.BasicDataSize-SAI_B_SyncSlave=SAI_PROTOCOL_DATASIZE_24BIT -SAI1.ErrorAudioFreq-SAI_A_MasterWithClock=-75.0 % -SAI1.IPParameters=Instance-SAI_A_MasterWithClock,VirtualMode-SAI_A_MasterWithClock,MClockEnable-SAI_A_MasterWithClock,RealAudioFreq-SAI_A_MasterWithClock,ErrorAudioFreq-SAI_A_MasterWithClock,InitProtocol-SAI_A_MasterWithClock,VirtualProtocol-SAI_A_BASIC,Instance-SAI_B_SyncSlave,VirtualMode-SAI_B_SyncSlave,InitProtocol-SAI_B_SyncSlave,VirtualProtocol-SAI_B_BASIC,BasicDataSize-SAI_A_MasterWithClock,BasicDataSize-SAI_B_SyncSlave,NoDivider-SAI_A_MasterWithClock +SAI1.ErrorAudioFreq-SAI_A_MasterWithClock=0.0 % +SAI1.FIFOThreshold-SAI_A_MasterWithClock=SAI_FIFOTHRESHOLD_EMPTY +SAI1.FIFOThreshold-SAI_B_SyncSlave=SAI_FIFOTHRESHOLD_EMPTY +SAI1.IPParameters=Instance-SAI_A_MasterWithClock,VirtualMode-SAI_A_MasterWithClock,MClockEnable-SAI_A_MasterWithClock,RealAudioFreq-SAI_A_MasterWithClock,ErrorAudioFreq-SAI_A_MasterWithClock,InitProtocol-SAI_A_MasterWithClock,VirtualProtocol-SAI_A_BASIC,Instance-SAI_B_SyncSlave,VirtualMode-SAI_B_SyncSlave,BasicDataSize-SAI_A_MasterWithClock,NoDivider-SAI_A_MasterWithClock,AudioFrequency-SAI_A_MasterWithClock,OutputDrive-SAI_A_MasterWithClock,FIFOThreshold-SAI_A_MasterWithClock,FIFOThreshold-SAI_B_SyncSlave,InitProtocol-SAI_B_SyncSlave,VirtualProtocol-SAI_B_BASIC,BasicDataSize-SAI_B_SyncSlave SAI1.InitProtocol-SAI_A_MasterWithClock=Enable SAI1.InitProtocol-SAI_B_SyncSlave=Enable SAI1.Instance-SAI_A_MasterWithClock=SAI$Index_Block_A SAI1.Instance-SAI_B_SyncSlave=SAI$Index_Block_B SAI1.MClockEnable-SAI_A_MasterWithClock=SAI_MASTERCLOCK_ENABLE SAI1.NoDivider-SAI_A_MasterWithClock=SAI_MCK_OVERSAMPLING_DISABLE +SAI1.OutputDrive-SAI_A_MasterWithClock=SAI_OUTPUTDRIVE_DISABLE SAI1.RealAudioFreq-SAI_A_MasterWithClock=48.0 KHz SAI1.VirtualMode-SAI_A_MasterWithClock=VM_MASTER SAI1.VirtualMode-SAI_B_SyncSlave=VM_SLAVE -- cgit v1.2.3