# firmware_test: работа с mqs

This commit is contained in:
Dmitry Akimov 2026-06-25 20:10:42 +03:00
parent 73b20d9f3e
commit 13cc7c6d0f
18 changed files with 1186 additions and 41 deletions

View file

@ -20,6 +20,7 @@ add_subdirectory(usb_cdc)
add_subdirectory(sdram) add_subdirectory(sdram)
add_subdirectory(qspi_flash) add_subdirectory(qspi_flash)
add_subdirectory(sd) add_subdirectory(sd)
add_subdirectory(mqs)
# Подавляем предупреждения при компиляции собственных .c файлов библиотеки # Подавляем предупреждения при компиляции собственных .c файлов библиотеки
target_compile_options(bsp_board PRIVATE -w) target_compile_options(bsp_board PRIVATE -w)

View file

@ -15,4 +15,5 @@ target_include_directories(
target_link_libraries( target_link_libraries(
bsp_can bsp_can
PUBLIC bsp_status PUBLIC bsp_status
PRIVATE bsp_tick utils sdk_flexcan $<$<BOOL:${BUILD_TESTS_HOST}>:fff>) PRIVATE bsp_tick utils sdk_clock sdk_flexcan
$<$<BOOL:${BUILD_TESTS_HOST}>:fff>)

View file

@ -22,6 +22,7 @@
#include "bsp/tick.h" #include "bsp/tick.h"
#include "clock_config.h" #include "clock_config.h"
#include "fsl_clock.h"
#include "fsl_flexcan.h" #include "fsl_flexcan.h"
#include "ring_buffer/ring_buffer.h" #include "ring_buffer/ring_buffer.h"

View file

@ -490,7 +490,7 @@
<clock_output id="LPI2C_CLK_ROOT.outFreq" value="60 MHz" locked="false" accuracy=""/> <clock_output id="LPI2C_CLK_ROOT.outFreq" value="60 MHz" locked="false" accuracy=""/>
<clock_output id="LPSPI_CLK_ROOT.outFreq" value="105.6 MHz" locked="false" accuracy=""/> <clock_output id="LPSPI_CLK_ROOT.outFreq" value="105.6 MHz" locked="false" accuracy=""/>
<clock_output id="LVDS1_CLK.outFreq" value="1.2 GHz" locked="false" accuracy=""/> <clock_output id="LVDS1_CLK.outFreq" value="1.2 GHz" locked="false" accuracy=""/>
<clock_output id="MQS_MCLK.outFreq" value="1080/17 MHz" locked="false" accuracy=""/> <clock_output id="MQS_MCLK.outFreq" value="2.8224 MHz" locked="false" accuracy=""/>
<clock_output id="PERCLK_CLK_ROOT.outFreq" value="75 MHz" locked="false" accuracy=""/> <clock_output id="PERCLK_CLK_ROOT.outFreq" value="75 MHz" locked="false" accuracy=""/>
<clock_output id="PLL7_MAIN_CLK.outFreq" value="24 MHz" locked="false" accuracy=""/> <clock_output id="PLL7_MAIN_CLK.outFreq" value="24 MHz" locked="false" accuracy=""/>
<clock_output id="SAI1_CLK_ROOT.outFreq" value="1080/17 MHz" locked="false" accuracy=""/> <clock_output id="SAI1_CLK_ROOT.outFreq" value="1080/17 MHz" locked="false" accuracy=""/>
@ -500,8 +500,8 @@
<clock_output id="SAI2_CLK_ROOT.outFreq" value="1080/17 MHz" locked="false" accuracy=""/> <clock_output id="SAI2_CLK_ROOT.outFreq" value="1080/17 MHz" locked="false" accuracy=""/>
<clock_output id="SAI2_MCLK1.outFreq" value="1080/17 MHz" locked="false" accuracy=""/> <clock_output id="SAI2_MCLK1.outFreq" value="1080/17 MHz" locked="false" accuracy=""/>
<clock_output id="SAI2_MCLK3.outFreq" value="30 MHz" locked="false" accuracy=""/> <clock_output id="SAI2_MCLK3.outFreq" value="30 MHz" locked="false" accuracy=""/>
<clock_output id="SAI3_CLK_ROOT.outFreq" value="1080/17 MHz" locked="false" accuracy=""/> <clock_output id="SAI3_CLK_ROOT.outFreq" value="11.2896 MHz" locked="false" accuracy=""/>
<clock_output id="SAI3_MCLK1.outFreq" value="1080/17 MHz" locked="false" accuracy=""/> <clock_output id="SAI3_MCLK1.outFreq" value="11.2896 MHz" locked="false" accuracy=""/>
<clock_output id="SAI3_MCLK3.outFreq" value="30 MHz" locked="false" accuracy=""/> <clock_output id="SAI3_MCLK3.outFreq" value="30 MHz" locked="false" accuracy=""/>
<clock_output id="SEMC_CLK_ROOT.outFreq" value="120 MHz" locked="false" accuracy=""/> <clock_output id="SEMC_CLK_ROOT.outFreq" value="120 MHz" locked="false" accuracy=""/>
<clock_output id="SPDIF0_CLK_ROOT.outFreq" value="30 MHz" locked="false" accuracy=""/> <clock_output id="SPDIF0_CLK_ROOT.outFreq" value="30 MHz" locked="false" accuracy=""/>
@ -519,6 +519,9 @@
<setting id="CCM.LPSPI_PODF.scale" value="5" locked="false"/> <setting id="CCM.LPSPI_PODF.scale" value="5" locked="false"/>
<setting id="CCM.PERCLK_PODF.scale" value="2" locked="true"/> <setting id="CCM.PERCLK_PODF.scale" value="2" locked="true"/>
<setting id="CCM.PERIPH_CLK2_SEL.sel" value="XTALOSC24M.OSC_CLK" locked="false"/> <setting id="CCM.PERIPH_CLK2_SEL.sel" value="XTALOSC24M.OSC_CLK" locked="false"/>
<setting id="CCM.SAI3_CLK_PODF.scale" value="8" locked="true"/>
<setting id="CCM.SAI3_CLK_PRED.scale" value="8" locked="true"/>
<setting id="CCM.SAI3_CLK_SEL.sel" value="CCM_ANALOG.PLL4_MAIN_CLK" locked="false"/>
<setting id="CCM.SEMC_PODF.scale" value="5" locked="true"/> <setting id="CCM.SEMC_PODF.scale" value="5" locked="true"/>
<setting id="CCM.USDHC1_CLK_SEL.sel" value="CCM_ANALOG.PLL2_PFD0_CLK" locked="false"/> <setting id="CCM.USDHC1_CLK_SEL.sel" value="CCM_ANALOG.PLL2_PFD0_CLK" locked="false"/>
<setting id="CCM.USDHC1_PODF.scale" value="2" locked="true"/> <setting id="CCM.USDHC1_PODF.scale" value="2" locked="true"/>
@ -540,9 +543,17 @@
<setting id="CCM_ANALOG.PLL3_PFD1_BYPASS.sel" value="CCM_ANALOG.PLL3_PFD1" locked="false"/> <setting id="CCM_ANALOG.PLL3_PFD1_BYPASS.sel" value="CCM_ANALOG.PLL3_PFD1" locked="false"/>
<setting id="CCM_ANALOG.PLL3_PFD2_BYPASS.sel" value="CCM_ANALOG.PLL3_PFD2" locked="false"/> <setting id="CCM_ANALOG.PLL3_PFD2_BYPASS.sel" value="CCM_ANALOG.PLL3_PFD2" locked="false"/>
<setting id="CCM_ANALOG.PLL3_PFD3_BYPASS.sel" value="CCM_ANALOG.PLL3_PFD3" locked="false"/> <setting id="CCM_ANALOG.PLL3_PFD3_BYPASS.sel" value="CCM_ANALOG.PLL3_PFD3" locked="false"/>
<setting id="CCM_ANALOG.PLL4.denom" value="625" locked="true"/>
<setting id="CCM_ANALOG.PLL4.div" value="30" locked="true"/>
<setting id="CCM_ANALOG.PLL4.num" value="66" locked="true"/>
<setting id="CCM_ANALOG.PLL4_BYPASS.sel" value="CCM_ANALOG.PLL4_POST_DIV" locked="false"/>
<setting id="CCM_ANALOG.PLL4_POST_DIV.scale" value="1" locked="true"/>
<setting id="CCM_ANALOG_PLL_AUDIO_POWERDOWN_CFG" value="No" locked="false"/>
<setting id="CCM_ANALOG_PLL_USB1_EN_USB_CLKS_CFG" value="Enabled" locked="false"/> <setting id="CCM_ANALOG_PLL_USB1_EN_USB_CLKS_CFG" value="Enabled" locked="false"/>
<setting id="CCM_ANALOG_PLL_USB1_EN_USB_CLKS_OUT_CFG" value="Enabled" locked="false"/> <setting id="CCM_ANALOG_PLL_USB1_EN_USB_CLKS_OUT_CFG" value="Enabled" locked="false"/>
<setting id="CCM_ANALOG_PLL_USB1_POWER_CFG" value="Yes" locked="false"/> <setting id="CCM_ANALOG_PLL_USB1_POWER_CFG" value="Yes" locked="false"/>
<setting id="IOMUXC_GPR.MQS_CLK_DIV.scale" value="4" locked="true"/>
<setting id="IOMUXC_GPR_GPR2_MQS_OVERSAMPLE" value="OverSampleRate64" locked="false"/>
</clock_settings> </clock_settings>
<called_from_default_init>true</called_from_default_init> <called_from_default_init>true</called_from_default_init>
</clock_configuration> </clock_configuration>

View file

@ -74,7 +74,7 @@ outputs:
- {id: LPI2C_CLK_ROOT.outFreq, value: 60 MHz} - {id: LPI2C_CLK_ROOT.outFreq, value: 60 MHz}
- {id: LPSPI_CLK_ROOT.outFreq, value: 105.6 MHz} - {id: LPSPI_CLK_ROOT.outFreq, value: 105.6 MHz}
- {id: LVDS1_CLK.outFreq, value: 1.2 GHz} - {id: LVDS1_CLK.outFreq, value: 1.2 GHz}
- {id: MQS_MCLK.outFreq, value: 1080/17 MHz} - {id: MQS_MCLK.outFreq, value: 2.8224 MHz}
- {id: PERCLK_CLK_ROOT.outFreq, value: 75 MHz} - {id: PERCLK_CLK_ROOT.outFreq, value: 75 MHz}
- {id: PLL7_MAIN_CLK.outFreq, value: 24 MHz} - {id: PLL7_MAIN_CLK.outFreq, value: 24 MHz}
- {id: SAI1_CLK_ROOT.outFreq, value: 1080/17 MHz} - {id: SAI1_CLK_ROOT.outFreq, value: 1080/17 MHz}
@ -84,8 +84,8 @@ outputs:
- {id: SAI2_CLK_ROOT.outFreq, value: 1080/17 MHz} - {id: SAI2_CLK_ROOT.outFreq, value: 1080/17 MHz}
- {id: SAI2_MCLK1.outFreq, value: 1080/17 MHz} - {id: SAI2_MCLK1.outFreq, value: 1080/17 MHz}
- {id: SAI2_MCLK3.outFreq, value: 30 MHz} - {id: SAI2_MCLK3.outFreq, value: 30 MHz}
- {id: SAI3_CLK_ROOT.outFreq, value: 1080/17 MHz} - {id: SAI3_CLK_ROOT.outFreq, value: 11.2896 MHz}
- {id: SAI3_MCLK1.outFreq, value: 1080/17 MHz} - {id: SAI3_MCLK1.outFreq, value: 11.2896 MHz}
- {id: SAI3_MCLK3.outFreq, value: 30 MHz} - {id: SAI3_MCLK3.outFreq, value: 30 MHz}
- {id: SEMC_CLK_ROOT.outFreq, value: 120 MHz} - {id: SEMC_CLK_ROOT.outFreq, value: 120 MHz}
- {id: SPDIF0_CLK_ROOT.outFreq, value: 30 MHz} - {id: SPDIF0_CLK_ROOT.outFreq, value: 30 MHz}
@ -102,6 +102,9 @@ settings:
- {id: CCM.LPSPI_PODF.scale, value: '5'} - {id: CCM.LPSPI_PODF.scale, value: '5'}
- {id: CCM.PERCLK_PODF.scale, value: '2', locked: true} - {id: CCM.PERCLK_PODF.scale, value: '2', locked: true}
- {id: CCM.PERIPH_CLK2_SEL.sel, value: XTALOSC24M.OSC_CLK} - {id: CCM.PERIPH_CLK2_SEL.sel, value: XTALOSC24M.OSC_CLK}
- {id: CCM.SAI3_CLK_PODF.scale, value: '8', locked: true}
- {id: CCM.SAI3_CLK_PRED.scale, value: '8', locked: true}
- {id: CCM.SAI3_CLK_SEL.sel, value: CCM_ANALOG.PLL4_MAIN_CLK}
- {id: CCM.SEMC_PODF.scale, value: '5', locked: true} - {id: CCM.SEMC_PODF.scale, value: '5', locked: true}
- {id: CCM.USDHC1_CLK_SEL.sel, value: CCM_ANALOG.PLL2_PFD0_CLK} - {id: CCM.USDHC1_CLK_SEL.sel, value: CCM_ANALOG.PLL2_PFD0_CLK}
- {id: CCM.USDHC1_PODF.scale, value: '2', locked: true} - {id: CCM.USDHC1_PODF.scale, value: '2', locked: true}
@ -123,9 +126,17 @@ settings:
- {id: CCM_ANALOG.PLL3_PFD1_BYPASS.sel, value: CCM_ANALOG.PLL3_PFD1} - {id: CCM_ANALOG.PLL3_PFD1_BYPASS.sel, value: CCM_ANALOG.PLL3_PFD1}
- {id: CCM_ANALOG.PLL3_PFD2_BYPASS.sel, value: CCM_ANALOG.PLL3_PFD2} - {id: CCM_ANALOG.PLL3_PFD2_BYPASS.sel, value: CCM_ANALOG.PLL3_PFD2}
- {id: CCM_ANALOG.PLL3_PFD3_BYPASS.sel, value: CCM_ANALOG.PLL3_PFD3} - {id: CCM_ANALOG.PLL3_PFD3_BYPASS.sel, value: CCM_ANALOG.PLL3_PFD3}
- {id: CCM_ANALOG.PLL4.denom, value: '625', locked: true}
- {id: CCM_ANALOG.PLL4.div, value: '30', locked: true}
- {id: CCM_ANALOG.PLL4.num, value: '66', locked: true}
- {id: CCM_ANALOG.PLL4_BYPASS.sel, value: CCM_ANALOG.PLL4_POST_DIV}
- {id: CCM_ANALOG.PLL4_POST_DIV.scale, value: '1', locked: true}
- {id: CCM_ANALOG_PLL_AUDIO_POWERDOWN_CFG, value: 'No'}
- {id: CCM_ANALOG_PLL_USB1_EN_USB_CLKS_CFG, value: Enabled} - {id: CCM_ANALOG_PLL_USB1_EN_USB_CLKS_CFG, value: Enabled}
- {id: CCM_ANALOG_PLL_USB1_EN_USB_CLKS_OUT_CFG, value: Enabled} - {id: CCM_ANALOG_PLL_USB1_EN_USB_CLKS_OUT_CFG, value: Enabled}
- {id: CCM_ANALOG_PLL_USB1_POWER_CFG, value: 'Yes'} - {id: CCM_ANALOG_PLL_USB1_POWER_CFG, value: 'Yes'}
- {id: IOMUXC_GPR.MQS_CLK_DIV.scale, value: '4', locked: true}
- {id: IOMUXC_GPR_GPR2_MQS_OVERSAMPLE, value: OverSampleRate64}
sources: sources:
- {id: XTALOSC24M.RTC_OSC.outFreq, value: 32.768 kHz, enabled: true} - {id: XTALOSC24M.RTC_OSC.outFreq, value: 32.768 kHz, enabled: true}
* BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/
@ -150,6 +161,14 @@ const clock_usb_pll_config_t usb1PllConfig_BOARD_BootClockRUN =
.loopDivider = 0, /* PLL loop divider, Fout = Fin * 20 */ .loopDivider = 0, /* PLL loop divider, Fout = Fin * 20 */
.src = 0, /* Bypass clock source, 0 - OSC 24M, 1 - CLK1_P and CLK1_N */ .src = 0, /* Bypass clock source, 0 - OSC 24M, 1 - CLK1_P and CLK1_N */
}; };
const clock_audio_pll_config_t audioPllConfig_BOARD_BootClockRUN =
{
.loopDivider = 30, /* PLL loop divider, Fout = Fin * ( loopDivider + numerator / denominator ) */
.postDivider = 1, /* Divider after PLL */
.numerator = 66, /* 30 bit numerator of fractional loop divider, Fout = Fin * ( loopDivider + numerator / denominator ) */
.denominator = 625, /* 30 bit denominator of fractional loop divider, Fout = Fin * ( loopDivider + numerator / denominator ) */
.src = 0, /* Bypass clock source, 0 - OSC 24M, 1 - CLK1_P and CLK1_N */
};
const clock_enet_pll_config_t enetPllConfig_BOARD_BootClockRUN = const clock_enet_pll_config_t enetPllConfig_BOARD_BootClockRUN =
{ {
.enableClkOutput = true, /* Enable the PLL providing the ENET 125MHz reference clock */ .enableClkOutput = true, /* Enable the PLL providing the ENET 125MHz reference clock */
@ -285,11 +304,11 @@ void BOARD_BootClockRUN(void)
/* Disable SAI3 clock gate. */ /* Disable SAI3 clock gate. */
CLOCK_DisableClock(kCLOCK_Sai3); CLOCK_DisableClock(kCLOCK_Sai3);
/* Set SAI3_CLK_PRED. */ /* Set SAI3_CLK_PRED. */
CLOCK_SetDiv(kCLOCK_Sai3PreDiv, 3); CLOCK_SetDiv(kCLOCK_Sai3PreDiv, 7);
/* Set SAI3_CLK_PODF. */ /* Set SAI3_CLK_PODF. */
CLOCK_SetDiv(kCLOCK_Sai3Div, 1); CLOCK_SetDiv(kCLOCK_Sai3Div, 7);
/* Set Sai3 clock source. */ /* Set Sai3 clock source. */
CLOCK_SetMux(kCLOCK_Sai3Mux, 0); CLOCK_SetMux(kCLOCK_Sai3Mux, 2);
/* Disable Lpi2c clock gate. */ /* Disable Lpi2c clock gate. */
CLOCK_DisableClock(kCLOCK_Lpi2c1); CLOCK_DisableClock(kCLOCK_Lpi2c1);
CLOCK_DisableClock(kCLOCK_Lpi2c2); CLOCK_DisableClock(kCLOCK_Lpi2c2);
@ -389,15 +408,26 @@ void BOARD_BootClockRUN(void)
/* Init Usb1 pfd3. */ /* Init Usb1 pfd3. */
CLOCK_InitUsb1Pfd(kCLOCK_Pfd3, 19); CLOCK_InitUsb1Pfd(kCLOCK_Pfd3, 19);
#endif #endif
/* DeInit Audio PLL. */ /* Init Audio PLL. */
CLOCK_DeinitAudioPll(); uint32_t pllAudio;
/* Bypass Audio PLL. */ /* Disable Audio PLL output before initial Audio PLL. */
CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_PllAudio, 1); CCM_ANALOG->PLL_AUDIO &= ~CCM_ANALOG_PLL_AUDIO_ENABLE_MASK;
/* Set divider for Audio PLL. */ /* Bypass PLL first */
CCM_ANALOG->PLL_AUDIO = (CCM_ANALOG->PLL_AUDIO & (~CCM_ANALOG_PLL_AUDIO_BYPASS_CLK_SRC_MASK)) |
CCM_ANALOG_PLL_AUDIO_BYPASS_MASK | CCM_ANALOG_PLL_AUDIO_BYPASS_CLK_SRC(0);
CCM_ANALOG->PLL_AUDIO_NUM = CCM_ANALOG_PLL_AUDIO_NUM_A(66);
CCM_ANALOG->PLL_AUDIO_DENOM = CCM_ANALOG_PLL_AUDIO_DENOM_B(625);
pllAudio = (CCM_ANALOG->PLL_AUDIO & (~(CCM_ANALOG_PLL_AUDIO_DIV_SELECT_MASK | CCM_ANALOG_PLL_AUDIO_POWERDOWN_MASK))) |
CCM_ANALOG_PLL_AUDIO_ENABLE_MASK | CCM_ANALOG_PLL_AUDIO_DIV_SELECT(30);
pllAudio |= CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(2);
CCM_ANALOG->MISC2 &= ~CCM_ANALOG_MISC2_AUDIO_DIV_LSB_MASK; CCM_ANALOG->MISC2 &= ~CCM_ANALOG_MISC2_AUDIO_DIV_LSB_MASK;
CCM_ANALOG->MISC2 &= ~CCM_ANALOG_MISC2_AUDIO_DIV_MSB_MASK; CCM_ANALOG->MISC2 &= ~CCM_ANALOG_MISC2_AUDIO_DIV_MSB_MASK;
/* Enable Audio PLL output. */ CCM_ANALOG->PLL_AUDIO = pllAudio;
CCM_ANALOG->PLL_AUDIO |= CCM_ANALOG_PLL_AUDIO_ENABLE_MASK; while ((CCM_ANALOG->PLL_AUDIO & CCM_ANALOG_PLL_AUDIO_LOCK_MASK) == 0)
{
}
/* Disable bypass for Audio PLL. */
CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_PllAudio, 0);
/* DeInit Video PLL. */ /* DeInit Video PLL. */
CLOCK_DeinitVideoPll(); CLOCK_DeinitVideoPll();
/* Bypass Video PLL. */ /* Bypass Video PLL. */
@ -451,7 +481,7 @@ void BOARD_BootClockRUN(void)
/* Set SAI3 MCLK3 clock source. */ /* Set SAI3 MCLK3 clock source. */
IOMUXC_SetSaiMClkClockSource(IOMUXC_GPR, kIOMUXC_GPR_SAI3MClk3Sel, 0); IOMUXC_SetSaiMClkClockSource(IOMUXC_GPR, kIOMUXC_GPR_SAI3MClk3Sel, 0);
/* Set MQS configuration. */ /* Set MQS configuration. */
IOMUXC_MQSConfig(IOMUXC_GPR,kIOMUXC_MqsPwmOverSampleRate32, 0); IOMUXC_MQSConfig(IOMUXC_GPR,kIOMUXC_MqsPwmOverSampleRate64, 3);
/* Set ENET Ref clock source. */ /* Set ENET Ref clock source. */
#if defined(IOMUXC_GPR_GPR1_ENET_REF_CLK_DIR_MASK) #if defined(IOMUXC_GPR_GPR1_ENET_REF_CLK_DIR_MASK)
IOMUXC_GPR->GPR1 &= ~IOMUXC_GPR_GPR1_ENET_REF_CLK_DIR_MASK; IOMUXC_GPR->GPR1 &= ~IOMUXC_GPR_GPR1_ENET_REF_CLK_DIR_MASK;

View file

@ -65,7 +65,7 @@ void BOARD_InitBootClocks(void);
#define BOARD_BOOTCLOCKRUN_LPI2C_CLK_ROOT 60000000UL /* Clock consumers of LPI2C_CLK_ROOT output : LPI2C1, LPI2C2, LPI2C3, LPI2C4 */ #define BOARD_BOOTCLOCKRUN_LPI2C_CLK_ROOT 60000000UL /* Clock consumers of LPI2C_CLK_ROOT output : LPI2C1, LPI2C2, LPI2C3, LPI2C4 */
#define BOARD_BOOTCLOCKRUN_LPSPI_CLK_ROOT 105600000UL /* Clock consumers of LPSPI_CLK_ROOT output : LPSPI1, LPSPI2, LPSPI3, LPSPI4 */ #define BOARD_BOOTCLOCKRUN_LPSPI_CLK_ROOT 105600000UL /* Clock consumers of LPSPI_CLK_ROOT output : LPSPI1, LPSPI2, LPSPI3, LPSPI4 */
#define BOARD_BOOTCLOCKRUN_LVDS1_CLK 1200000000UL /* Clock consumers of LVDS1_CLK output : N/A */ #define BOARD_BOOTCLOCKRUN_LVDS1_CLK 1200000000UL /* Clock consumers of LVDS1_CLK output : N/A */
#define BOARD_BOOTCLOCKRUN_MQS_MCLK 63529411UL /* Clock consumers of MQS_MCLK output : N/A */ #define BOARD_BOOTCLOCKRUN_MQS_MCLK 2822400UL /* Clock consumers of MQS_MCLK output : N/A */
#define BOARD_BOOTCLOCKRUN_PERCLK_CLK_ROOT 75000000UL /* Clock consumers of PERCLK_CLK_ROOT output : GPT1, GPT2, PIT */ #define BOARD_BOOTCLOCKRUN_PERCLK_CLK_ROOT 75000000UL /* Clock consumers of PERCLK_CLK_ROOT output : GPT1, GPT2, PIT */
#define BOARD_BOOTCLOCKRUN_PLL7_MAIN_CLK 24000000UL /* Clock consumers of PLL7_MAIN_CLK output : N/A */ #define BOARD_BOOTCLOCKRUN_PLL7_MAIN_CLK 24000000UL /* Clock consumers of PLL7_MAIN_CLK output : N/A */
#define BOARD_BOOTCLOCKRUN_SAI1_CLK_ROOT 63529411UL /* Clock consumers of SAI1_CLK_ROOT output : N/A */ #define BOARD_BOOTCLOCKRUN_SAI1_CLK_ROOT 63529411UL /* Clock consumers of SAI1_CLK_ROOT output : N/A */
@ -76,8 +76,8 @@ void BOARD_InitBootClocks(void);
#define BOARD_BOOTCLOCKRUN_SAI2_MCLK1 63529411UL /* Clock consumers of SAI2_MCLK1 output : SAI2 */ #define BOARD_BOOTCLOCKRUN_SAI2_MCLK1 63529411UL /* Clock consumers of SAI2_MCLK1 output : SAI2 */
#define BOARD_BOOTCLOCKRUN_SAI2_MCLK2 0UL /* Clock consumers of SAI2_MCLK2 output : SAI2 */ #define BOARD_BOOTCLOCKRUN_SAI2_MCLK2 0UL /* Clock consumers of SAI2_MCLK2 output : SAI2 */
#define BOARD_BOOTCLOCKRUN_SAI2_MCLK3 30000000UL /* Clock consumers of SAI2_MCLK3 output : SAI2 */ #define BOARD_BOOTCLOCKRUN_SAI2_MCLK3 30000000UL /* Clock consumers of SAI2_MCLK3 output : SAI2 */
#define BOARD_BOOTCLOCKRUN_SAI3_CLK_ROOT 63529411UL /* Clock consumers of SAI3_CLK_ROOT output : N/A */ #define BOARD_BOOTCLOCKRUN_SAI3_CLK_ROOT 11289600UL /* Clock consumers of SAI3_CLK_ROOT output : N/A */
#define BOARD_BOOTCLOCKRUN_SAI3_MCLK1 63529411UL /* Clock consumers of SAI3_MCLK1 output : SAI3 */ #define BOARD_BOOTCLOCKRUN_SAI3_MCLK1 11289600UL /* Clock consumers of SAI3_MCLK1 output : SAI3 */
#define BOARD_BOOTCLOCKRUN_SAI3_MCLK2 0UL /* Clock consumers of SAI3_MCLK2 output : SAI3 */ #define BOARD_BOOTCLOCKRUN_SAI3_MCLK2 0UL /* Clock consumers of SAI3_MCLK2 output : SAI3 */
#define BOARD_BOOTCLOCKRUN_SAI3_MCLK3 30000000UL /* Clock consumers of SAI3_MCLK3 output : SAI3 */ #define BOARD_BOOTCLOCKRUN_SAI3_MCLK3 30000000UL /* Clock consumers of SAI3_MCLK3 output : SAI3 */
#define BOARD_BOOTCLOCKRUN_SEMC_CLK_ROOT 120000000UL /* Clock consumers of SEMC_CLK_ROOT output : SEMC */ #define BOARD_BOOTCLOCKRUN_SEMC_CLK_ROOT 120000000UL /* Clock consumers of SEMC_CLK_ROOT output : SEMC */
@ -99,6 +99,9 @@ extern const clock_usb_pll_config_t usb1PllConfig_BOARD_BootClockRUN;
/*! @brief Sys PLL for BOARD_BootClockRUN configuration. /*! @brief Sys PLL for BOARD_BootClockRUN configuration.
*/ */
extern const clock_sys_pll_config_t sysPllConfig_BOARD_BootClockRUN; extern const clock_sys_pll_config_t sysPllConfig_BOARD_BootClockRUN;
/*! @brief Audio PLL set for BOARD_BootClockRUN configuration.
*/
extern const clock_audio_pll_config_t audioPllConfig_BOARD_BootClockRUN;
/*! @brief Enet PLL set for BOARD_BootClockRUN configuration. /*! @brief Enet PLL set for BOARD_BootClockRUN configuration.
*/ */
extern const clock_enet_pll_config_t enetPllConfig_BOARD_BootClockRUN; extern const clock_enet_pll_config_t enetPllConfig_BOARD_BootClockRUN;

View file

@ -74,7 +74,7 @@ outputs:
- {id: LPI2C_CLK_ROOT.outFreq, value: 60 MHz} - {id: LPI2C_CLK_ROOT.outFreq, value: 60 MHz}
- {id: LPSPI_CLK_ROOT.outFreq, value: 105.6 MHz} - {id: LPSPI_CLK_ROOT.outFreq, value: 105.6 MHz}
- {id: LVDS1_CLK.outFreq, value: 1.2 GHz} - {id: LVDS1_CLK.outFreq, value: 1.2 GHz}
- {id: MQS_MCLK.outFreq, value: 1080/17 MHz} - {id: MQS_MCLK.outFreq, value: 2.8224 MHz}
- {id: PERCLK_CLK_ROOT.outFreq, value: 75 MHz} - {id: PERCLK_CLK_ROOT.outFreq, value: 75 MHz}
- {id: PLL7_MAIN_CLK.outFreq, value: 24 MHz} - {id: PLL7_MAIN_CLK.outFreq, value: 24 MHz}
- {id: SAI1_CLK_ROOT.outFreq, value: 1080/17 MHz} - {id: SAI1_CLK_ROOT.outFreq, value: 1080/17 MHz}
@ -84,8 +84,8 @@ outputs:
- {id: SAI2_CLK_ROOT.outFreq, value: 1080/17 MHz} - {id: SAI2_CLK_ROOT.outFreq, value: 1080/17 MHz}
- {id: SAI2_MCLK1.outFreq, value: 1080/17 MHz} - {id: SAI2_MCLK1.outFreq, value: 1080/17 MHz}
- {id: SAI2_MCLK3.outFreq, value: 30 MHz} - {id: SAI2_MCLK3.outFreq, value: 30 MHz}
- {id: SAI3_CLK_ROOT.outFreq, value: 1080/17 MHz} - {id: SAI3_CLK_ROOT.outFreq, value: 11.2896 MHz}
- {id: SAI3_MCLK1.outFreq, value: 1080/17 MHz} - {id: SAI3_MCLK1.outFreq, value: 11.2896 MHz}
- {id: SAI3_MCLK3.outFreq, value: 30 MHz} - {id: SAI3_MCLK3.outFreq, value: 30 MHz}
- {id: SEMC_CLK_ROOT.outFreq, value: 120 MHz} - {id: SEMC_CLK_ROOT.outFreq, value: 120 MHz}
- {id: SPDIF0_CLK_ROOT.outFreq, value: 30 MHz} - {id: SPDIF0_CLK_ROOT.outFreq, value: 30 MHz}
@ -102,6 +102,9 @@ settings:
- {id: CCM.LPSPI_PODF.scale, value: '5'} - {id: CCM.LPSPI_PODF.scale, value: '5'}
- {id: CCM.PERCLK_PODF.scale, value: '2', locked: true} - {id: CCM.PERCLK_PODF.scale, value: '2', locked: true}
- {id: CCM.PERIPH_CLK2_SEL.sel, value: XTALOSC24M.OSC_CLK} - {id: CCM.PERIPH_CLK2_SEL.sel, value: XTALOSC24M.OSC_CLK}
- {id: CCM.SAI3_CLK_PODF.scale, value: '8', locked: true}
- {id: CCM.SAI3_CLK_PRED.scale, value: '8', locked: true}
- {id: CCM.SAI3_CLK_SEL.sel, value: CCM_ANALOG.PLL4_MAIN_CLK}
- {id: CCM.SEMC_PODF.scale, value: '5', locked: true} - {id: CCM.SEMC_PODF.scale, value: '5', locked: true}
- {id: CCM.USDHC1_CLK_SEL.sel, value: CCM_ANALOG.PLL2_PFD0_CLK} - {id: CCM.USDHC1_CLK_SEL.sel, value: CCM_ANALOG.PLL2_PFD0_CLK}
- {id: CCM.USDHC1_PODF.scale, value: '2', locked: true} - {id: CCM.USDHC1_PODF.scale, value: '2', locked: true}
@ -123,9 +126,17 @@ settings:
- {id: CCM_ANALOG.PLL3_PFD1_BYPASS.sel, value: CCM_ANALOG.PLL3_PFD1} - {id: CCM_ANALOG.PLL3_PFD1_BYPASS.sel, value: CCM_ANALOG.PLL3_PFD1}
- {id: CCM_ANALOG.PLL3_PFD2_BYPASS.sel, value: CCM_ANALOG.PLL3_PFD2} - {id: CCM_ANALOG.PLL3_PFD2_BYPASS.sel, value: CCM_ANALOG.PLL3_PFD2}
- {id: CCM_ANALOG.PLL3_PFD3_BYPASS.sel, value: CCM_ANALOG.PLL3_PFD3} - {id: CCM_ANALOG.PLL3_PFD3_BYPASS.sel, value: CCM_ANALOG.PLL3_PFD3}
- {id: CCM_ANALOG.PLL4.denom, value: '625', locked: true}
- {id: CCM_ANALOG.PLL4.div, value: '30', locked: true}
- {id: CCM_ANALOG.PLL4.num, value: '66', locked: true}
- {id: CCM_ANALOG.PLL4_BYPASS.sel, value: CCM_ANALOG.PLL4_POST_DIV}
- {id: CCM_ANALOG.PLL4_POST_DIV.scale, value: '1', locked: true}
- {id: CCM_ANALOG_PLL_AUDIO_POWERDOWN_CFG, value: 'No'}
- {id: CCM_ANALOG_PLL_USB1_EN_USB_CLKS_CFG, value: Enabled} - {id: CCM_ANALOG_PLL_USB1_EN_USB_CLKS_CFG, value: Enabled}
- {id: CCM_ANALOG_PLL_USB1_EN_USB_CLKS_OUT_CFG, value: Enabled} - {id: CCM_ANALOG_PLL_USB1_EN_USB_CLKS_OUT_CFG, value: Enabled}
- {id: CCM_ANALOG_PLL_USB1_POWER_CFG, value: 'Yes'} - {id: CCM_ANALOG_PLL_USB1_POWER_CFG, value: 'Yes'}
- {id: IOMUXC_GPR.MQS_CLK_DIV.scale, value: '4', locked: true}
- {id: IOMUXC_GPR_GPR2_MQS_OVERSAMPLE, value: OverSampleRate64}
sources: sources:
- {id: XTALOSC24M.RTC_OSC.outFreq, value: 32.768 kHz, enabled: true} - {id: XTALOSC24M.RTC_OSC.outFreq, value: 32.768 kHz, enabled: true}
* BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/
@ -150,6 +161,14 @@ const clock_usb_pll_config_t usb1PllConfig_BOARD_BootClockRUN =
.loopDivider = 0, /* PLL loop divider, Fout = Fin * 20 */ .loopDivider = 0, /* PLL loop divider, Fout = Fin * 20 */
.src = 0, /* Bypass clock source, 0 - OSC 24M, 1 - CLK1_P and CLK1_N */ .src = 0, /* Bypass clock source, 0 - OSC 24M, 1 - CLK1_P and CLK1_N */
}; };
const clock_audio_pll_config_t audioPllConfig_BOARD_BootClockRUN =
{
.loopDivider = 30, /* PLL loop divider, Fout = Fin * ( loopDivider + numerator / denominator ) */
.postDivider = 1, /* Divider after PLL */
.numerator = 66, /* 30 bit numerator of fractional loop divider, Fout = Fin * ( loopDivider + numerator / denominator ) */
.denominator = 625, /* 30 bit denominator of fractional loop divider, Fout = Fin * ( loopDivider + numerator / denominator ) */
.src = 0, /* Bypass clock source, 0 - OSC 24M, 1 - CLK1_P and CLK1_N */
};
const clock_enet_pll_config_t enetPllConfig_BOARD_BootClockRUN = const clock_enet_pll_config_t enetPllConfig_BOARD_BootClockRUN =
{ {
.enableClkOutput = true, /* Enable the PLL providing the ENET 125MHz reference clock */ .enableClkOutput = true, /* Enable the PLL providing the ENET 125MHz reference clock */
@ -285,11 +304,11 @@ void BOARD_BootClockRUN(void)
/* Disable SAI3 clock gate. */ /* Disable SAI3 clock gate. */
CLOCK_DisableClock(kCLOCK_Sai3); CLOCK_DisableClock(kCLOCK_Sai3);
/* Set SAI3_CLK_PRED. */ /* Set SAI3_CLK_PRED. */
CLOCK_SetDiv(kCLOCK_Sai3PreDiv, 3); CLOCK_SetDiv(kCLOCK_Sai3PreDiv, 7);
/* Set SAI3_CLK_PODF. */ /* Set SAI3_CLK_PODF. */
CLOCK_SetDiv(kCLOCK_Sai3Div, 1); CLOCK_SetDiv(kCLOCK_Sai3Div, 7);
/* Set Sai3 clock source. */ /* Set Sai3 clock source. */
CLOCK_SetMux(kCLOCK_Sai3Mux, 0); CLOCK_SetMux(kCLOCK_Sai3Mux, 2);
/* Disable Lpi2c clock gate. */ /* Disable Lpi2c clock gate. */
CLOCK_DisableClock(kCLOCK_Lpi2c1); CLOCK_DisableClock(kCLOCK_Lpi2c1);
CLOCK_DisableClock(kCLOCK_Lpi2c2); CLOCK_DisableClock(kCLOCK_Lpi2c2);
@ -389,15 +408,26 @@ void BOARD_BootClockRUN(void)
/* Init Usb1 pfd3. */ /* Init Usb1 pfd3. */
CLOCK_InitUsb1Pfd(kCLOCK_Pfd3, 19); CLOCK_InitUsb1Pfd(kCLOCK_Pfd3, 19);
#endif #endif
/* DeInit Audio PLL. */ /* Init Audio PLL. */
CLOCK_DeinitAudioPll(); uint32_t pllAudio;
/* Bypass Audio PLL. */ /* Disable Audio PLL output before initial Audio PLL. */
CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_PllAudio, 1); CCM_ANALOG->PLL_AUDIO &= ~CCM_ANALOG_PLL_AUDIO_ENABLE_MASK;
/* Set divider for Audio PLL. */ /* Bypass PLL first */
CCM_ANALOG->PLL_AUDIO = (CCM_ANALOG->PLL_AUDIO & (~CCM_ANALOG_PLL_AUDIO_BYPASS_CLK_SRC_MASK)) |
CCM_ANALOG_PLL_AUDIO_BYPASS_MASK | CCM_ANALOG_PLL_AUDIO_BYPASS_CLK_SRC(0);
CCM_ANALOG->PLL_AUDIO_NUM = CCM_ANALOG_PLL_AUDIO_NUM_A(66);
CCM_ANALOG->PLL_AUDIO_DENOM = CCM_ANALOG_PLL_AUDIO_DENOM_B(625);
pllAudio = (CCM_ANALOG->PLL_AUDIO & (~(CCM_ANALOG_PLL_AUDIO_DIV_SELECT_MASK | CCM_ANALOG_PLL_AUDIO_POWERDOWN_MASK))) |
CCM_ANALOG_PLL_AUDIO_ENABLE_MASK | CCM_ANALOG_PLL_AUDIO_DIV_SELECT(30);
pllAudio |= CCM_ANALOG_PLL_AUDIO_POST_DIV_SELECT(2);
CCM_ANALOG->MISC2 &= ~CCM_ANALOG_MISC2_AUDIO_DIV_LSB_MASK; CCM_ANALOG->MISC2 &= ~CCM_ANALOG_MISC2_AUDIO_DIV_LSB_MASK;
CCM_ANALOG->MISC2 &= ~CCM_ANALOG_MISC2_AUDIO_DIV_MSB_MASK; CCM_ANALOG->MISC2 &= ~CCM_ANALOG_MISC2_AUDIO_DIV_MSB_MASK;
/* Enable Audio PLL output. */ CCM_ANALOG->PLL_AUDIO = pllAudio;
CCM_ANALOG->PLL_AUDIO |= CCM_ANALOG_PLL_AUDIO_ENABLE_MASK; while ((CCM_ANALOG->PLL_AUDIO & CCM_ANALOG_PLL_AUDIO_LOCK_MASK) == 0)
{
}
/* Disable bypass for Audio PLL. */
CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_PllAudio, 0);
/* DeInit Video PLL. */ /* DeInit Video PLL. */
CLOCK_DeinitVideoPll(); CLOCK_DeinitVideoPll();
/* Bypass Video PLL. */ /* Bypass Video PLL. */
@ -451,7 +481,7 @@ void BOARD_BootClockRUN(void)
/* Set SAI3 MCLK3 clock source. */ /* Set SAI3 MCLK3 clock source. */
IOMUXC_SetSaiMClkClockSource(IOMUXC_GPR, kIOMUXC_GPR_SAI3MClk3Sel, 0); IOMUXC_SetSaiMClkClockSource(IOMUXC_GPR, kIOMUXC_GPR_SAI3MClk3Sel, 0);
/* Set MQS configuration. */ /* Set MQS configuration. */
IOMUXC_MQSConfig(IOMUXC_GPR,kIOMUXC_MqsPwmOverSampleRate32, 0); IOMUXC_MQSConfig(IOMUXC_GPR,kIOMUXC_MqsPwmOverSampleRate64, 3);
/* Set ENET Ref clock source. */ /* Set ENET Ref clock source. */
#if defined(IOMUXC_GPR_GPR1_ENET_REF_CLK_DIR_MASK) #if defined(IOMUXC_GPR_GPR1_ENET_REF_CLK_DIR_MASK)
IOMUXC_GPR->GPR1 &= ~IOMUXC_GPR_GPR1_ENET_REF_CLK_DIR_MASK; IOMUXC_GPR->GPR1 &= ~IOMUXC_GPR_GPR1_ENET_REF_CLK_DIR_MASK;

View file

@ -65,7 +65,7 @@ void BOARD_InitBootClocks(void);
#define BOARD_BOOTCLOCKRUN_LPI2C_CLK_ROOT 60000000UL /* Clock consumers of LPI2C_CLK_ROOT output : LPI2C1, LPI2C2, LPI2C3, LPI2C4 */ #define BOARD_BOOTCLOCKRUN_LPI2C_CLK_ROOT 60000000UL /* Clock consumers of LPI2C_CLK_ROOT output : LPI2C1, LPI2C2, LPI2C3, LPI2C4 */
#define BOARD_BOOTCLOCKRUN_LPSPI_CLK_ROOT 105600000UL /* Clock consumers of LPSPI_CLK_ROOT output : LPSPI1, LPSPI2, LPSPI3, LPSPI4 */ #define BOARD_BOOTCLOCKRUN_LPSPI_CLK_ROOT 105600000UL /* Clock consumers of LPSPI_CLK_ROOT output : LPSPI1, LPSPI2, LPSPI3, LPSPI4 */
#define BOARD_BOOTCLOCKRUN_LVDS1_CLK 1200000000UL /* Clock consumers of LVDS1_CLK output : N/A */ #define BOARD_BOOTCLOCKRUN_LVDS1_CLK 1200000000UL /* Clock consumers of LVDS1_CLK output : N/A */
#define BOARD_BOOTCLOCKRUN_MQS_MCLK 63529411UL /* Clock consumers of MQS_MCLK output : N/A */ #define BOARD_BOOTCLOCKRUN_MQS_MCLK 2822400UL /* Clock consumers of MQS_MCLK output : N/A */
#define BOARD_BOOTCLOCKRUN_PERCLK_CLK_ROOT 75000000UL /* Clock consumers of PERCLK_CLK_ROOT output : GPT1, GPT2, PIT */ #define BOARD_BOOTCLOCKRUN_PERCLK_CLK_ROOT 75000000UL /* Clock consumers of PERCLK_CLK_ROOT output : GPT1, GPT2, PIT */
#define BOARD_BOOTCLOCKRUN_PLL7_MAIN_CLK 24000000UL /* Clock consumers of PLL7_MAIN_CLK output : N/A */ #define BOARD_BOOTCLOCKRUN_PLL7_MAIN_CLK 24000000UL /* Clock consumers of PLL7_MAIN_CLK output : N/A */
#define BOARD_BOOTCLOCKRUN_SAI1_CLK_ROOT 63529411UL /* Clock consumers of SAI1_CLK_ROOT output : N/A */ #define BOARD_BOOTCLOCKRUN_SAI1_CLK_ROOT 63529411UL /* Clock consumers of SAI1_CLK_ROOT output : N/A */
@ -76,8 +76,8 @@ void BOARD_InitBootClocks(void);
#define BOARD_BOOTCLOCKRUN_SAI2_MCLK1 63529411UL /* Clock consumers of SAI2_MCLK1 output : SAI2 */ #define BOARD_BOOTCLOCKRUN_SAI2_MCLK1 63529411UL /* Clock consumers of SAI2_MCLK1 output : SAI2 */
#define BOARD_BOOTCLOCKRUN_SAI2_MCLK2 0UL /* Clock consumers of SAI2_MCLK2 output : SAI2 */ #define BOARD_BOOTCLOCKRUN_SAI2_MCLK2 0UL /* Clock consumers of SAI2_MCLK2 output : SAI2 */
#define BOARD_BOOTCLOCKRUN_SAI2_MCLK3 30000000UL /* Clock consumers of SAI2_MCLK3 output : SAI2 */ #define BOARD_BOOTCLOCKRUN_SAI2_MCLK3 30000000UL /* Clock consumers of SAI2_MCLK3 output : SAI2 */
#define BOARD_BOOTCLOCKRUN_SAI3_CLK_ROOT 63529411UL /* Clock consumers of SAI3_CLK_ROOT output : N/A */ #define BOARD_BOOTCLOCKRUN_SAI3_CLK_ROOT 11289600UL /* Clock consumers of SAI3_CLK_ROOT output : N/A */
#define BOARD_BOOTCLOCKRUN_SAI3_MCLK1 63529411UL /* Clock consumers of SAI3_MCLK1 output : SAI3 */ #define BOARD_BOOTCLOCKRUN_SAI3_MCLK1 11289600UL /* Clock consumers of SAI3_MCLK1 output : SAI3 */
#define BOARD_BOOTCLOCKRUN_SAI3_MCLK2 0UL /* Clock consumers of SAI3_MCLK2 output : SAI3 */ #define BOARD_BOOTCLOCKRUN_SAI3_MCLK2 0UL /* Clock consumers of SAI3_MCLK2 output : SAI3 */
#define BOARD_BOOTCLOCKRUN_SAI3_MCLK3 30000000UL /* Clock consumers of SAI3_MCLK3 output : SAI3 */ #define BOARD_BOOTCLOCKRUN_SAI3_MCLK3 30000000UL /* Clock consumers of SAI3_MCLK3 output : SAI3 */
#define BOARD_BOOTCLOCKRUN_SEMC_CLK_ROOT 120000000UL /* Clock consumers of SEMC_CLK_ROOT output : SEMC */ #define BOARD_BOOTCLOCKRUN_SEMC_CLK_ROOT 120000000UL /* Clock consumers of SEMC_CLK_ROOT output : SEMC */
@ -99,6 +99,9 @@ extern const clock_usb_pll_config_t usb1PllConfig_BOARD_BootClockRUN;
/*! @brief Sys PLL for BOARD_BootClockRUN configuration. /*! @brief Sys PLL for BOARD_BootClockRUN configuration.
*/ */
extern const clock_sys_pll_config_t sysPllConfig_BOARD_BootClockRUN; extern const clock_sys_pll_config_t sysPllConfig_BOARD_BootClockRUN;
/*! @brief Audio PLL set for BOARD_BootClockRUN configuration.
*/
extern const clock_audio_pll_config_t audioPllConfig_BOARD_BootClockRUN;
/*! @brief Enet PLL set for BOARD_BootClockRUN configuration. /*! @brief Enet PLL set for BOARD_BootClockRUN configuration.
*/ */
extern const clock_enet_pll_config_t enetPllConfig_BOARD_BootClockRUN; extern const clock_enet_pll_config_t enetPllConfig_BOARD_BootClockRUN;

18
bsp/mqs/CMakeLists.txt Normal file
View file

@ -0,0 +1,18 @@
# bsp/mqs/CMakeLists.txt
if(BUILD_TESTS_HOST)
return()
endif()
add_library(bsp_mqs STATIC src/mqs.c src/mqs_amp.c)
target_include_directories(
bsp_mqs
PUBLIC include/
PRIVATE src/)
target_link_libraries(
bsp_mqs
PUBLIC bsp_status
PUBLIC bsp_board
PRIVATE sdk_sai_edma sdk_edma sdk_dmamux sdk_clock sdk_pwm sdk_xbara)

0
bsp/mqs/README.md Normal file
View file

181
bsp/mqs/include/bsp/mqs.h Normal file
View file

@ -0,0 +1,181 @@
/**
* @file bsp/mqs.h
* @brief BSP: Medium Quality Sound (MQS) SAI1 + eDMA + MQS.
*
* Слой абстракции над SAI1/eDMA/MQS для монофонического аудио-выхода.
* Физически на плате выведен один канал (MQS_RIGHT, GPIO_AD_B0_04);
* SAI1 требует стерео-буфер оба канала всегда идентичны.
*
* Режимы использования:
* - firmware_test: bsp_mqs_play_blocking() синхронная подача
* статического буфера, polling-флаг завершения.
* - tft_app: bsp_mqs_play() + колбэк асинхронная потоковая
* подача буферов из задачи FreeRTOS.
*
* Ограничения:
* - Буфер должен быть в некэшируемой памяти (AT_NONCACHEABLE_SECTION_ALIGN)
* или кэш должен быть явно вычищен перед вызовом bsp_mqs_play().
* - Одновременно может воспроизводиться только один буфер.
* - bsp_mqs_init() вызывается однократно; повторный вызов без
* bsp_mqs_deinit() возвращает BSP_OK без переинициализации.
*/
#ifndef BSP_MQS_H
#define BSP_MQS_H
#include "bsp/status.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C"
{
#endif
/* --------------------------------------------------------------------------
* Параметры аудио-потока
* ----------------------------------------------------------------------- */
/** Частота дискретизации, Гц. Небольшое отклонение (~0.5%) из-за
* источника SAI1_CLK_ROOT (System PLL PFD2, не Audio PLL). */
#define BSP_MQS_SAMPLE_RATE_HZ (44100U)
/** Разрядность PCM. MQS поддерживает только 16 бит. */
#define BSP_MQS_BIT_WIDTH (16U)
/** Количество каналов в буфере. SAI1+MQS требует стерео; правый == левый. */
#define BSP_MQS_CHANNELS (2U)
/** Байт на один моно-сэмпл (16 бит → 2 байта). */
#define BSP_MQS_BYTES_PER_SAMPLE (BSP_MQS_BIT_WIDTH / 8U)
/** Байт на один стерео-фрейм (L + R). */
#define BSP_MQS_BYTES_PER_FRAME (BSP_MQS_BYTES_PER_SAMPLE * BSP_MQS_CHANNELS)
/* --------------------------------------------------------------------------
* Колбэк завершения (для tft_app / потокового режима)
* ----------------------------------------------------------------------- */
/**
* @brief Колбэк завершения DMA-передачи одного буфера.
*
* Вызывается из контекста ISR. Запрещено: блокировки, HAL-функции
* без суффикса _FromISR, длительные вычисления.
*
* @param p_user Пользовательский указатель, переданный в bsp_mqs_play().
*/
typedef void (*bsp_mqs_done_cb_t)(void *p_user);
/* --------------------------------------------------------------------------
* API
* ----------------------------------------------------------------------- */
/**
* @brief Инициализация MQS-подсистемы: SAI1, eDMA, DMAMUX, MQS.
*
* Включает тактирование SAI1 (kCLOCK_Sai1), настраивает SAI1 в режиме
* TX Master, 16 бит, стерео, 44100 Гц, инициализирует eDMA канал 0
* (DMAMUX source kDmaRequestMuxSai1Tx) и MQS-модуль.
*
* Пин GPIO_AD_B0_04 (MQS_RIGHT) уже замультиплексирован в BOARD_InitPins().
* MQS oversample (×32) уже выставлен в BOARD_BootClockRUN().
*
* @return BSP_OK успех
* @return BSP_ERR_HW eDMA или SAI вернул ошибку при настройке формата
*/
bsp_status_t bsp_mqs_init(void);
/**
* @brief Деинициализация: остановить DMA, сбросить SAI1 и MQS.
*
* Безопасно вызывать даже если воспроизведение уже завершилось.
* После вызова модуль требует повторного bsp_mqs_init().
*/
void bsp_mqs_deinit(void);
/**
* @brief Запустить асинхронное воспроизведение буфера через eDMA.
*
* Буфер должен содержать стерео PCM16 interleaved (L0, R0, L1, R1, ).
* Указатель @p p_buf обязан оставаться валидным до срабатывания колбэка @p cb.
*
* @param p_buf Указатель на стерео PCM16 буфер (некэшируемая память).
* @param n_frames Число стерео-фреймов (не байт, не сэмплов).
* @param cb Колбэк завершения; NULL без уведомления.
* @param p_user Аргумент для колбэка; NULL допустим.
*
* @return BSP_OK передача запущена
* @return BSP_ERR_BUSY предыдущая передача ещё не завершена
* @return BSP_ERR_INVALID p_buf == NULL или n_frames == 0
* @return BSP_ERR_HW SAI_TransferSendEDMA вернул ошибку
*/
bsp_status_t bsp_mqs_play(const int16_t *p_buf, size_t n_frames, bsp_mqs_done_cb_t cb,
void *p_user);
/**
* @brief Синхронное воспроизведение: запустить и дождаться завершения.
*
* Вызывает bsp_mqs_play() и крутится в polling-цикле до сброса флага
* завершения. Предназначен для bare-metal (firmware_test).
* Не вызывать из ISR или FreeRTOS-задачи с высоким приоритетом.
*
* @param p_buf Указатель на стерео PCM16 буфер (некэшируемая память).
* @param n_frames Число стерео-фреймов.
*
* @return BSP_OK воспроизведение завершено
* @return BSP_ERR_BUSY предыдущая передача ещё не завершена
* @return BSP_ERR_INVALID p_buf == NULL или n_frames == 0
* @return BSP_ERR_HW SAI_TransferSendEDMA вернул ошибку
*/
bsp_status_t bsp_mqs_play_blocking(const int16_t *p_buf, size_t n_frames);
/**
* @brief Немедленно прервать воспроизведение.
*
* Останавливает текущую DMA-передачу. Колбэк после stop НЕ вызывается.
* Безопасно вызывать если передача уже завершилась.
*/
void bsp_mqs_stop(void);
/**
* @brief Проверить, активна ли DMA-передача.
*
* @return true передача идёт
* @return false передача завершена или не была запущена
*/
bool bsp_mqs_is_busy(void);
/* --------------------------------------------------------------------------
* Усилитель (LM4875M, управление через PWM4 SM0 PWM_A)
* ----------------------------------------------------------------------- */
/**
* @brief Инициализация усилителя: PWM4 SM0, 16 кГц, duty 50%.
*
* Настраивает XBARA1 (fault disable), PWM4 submodule 0 channel A.
* Вызывать до bsp_mqs_play() без ШИМ на VOLUME усиление равно нулю.
*
* @return BSP_OK успех
* @return BSP_ERR_HW PWM_Init или PWM_SetupPwm вернул ошибку
*/
bsp_status_t bsp_mqs_amp_init(void);
/**
* @brief Установить уровень громкости (duty cycle PWM).
*
* @param percent Громкость 0100%. 0 = тишина, 50 = номинал, 100 = макс.
*/
void bsp_mqs_amp_set_volume(uint8_t percent);
/**
* @brief Деинициализация усилителя: duty 0%, стоп таймера.
*/
void bsp_mqs_amp_deinit(void);
#ifdef __cplusplus
}
#endif
#endif /* BSP_MQS_H */

286
bsp/mqs/src/mqs.c Normal file
View file

@ -0,0 +1,286 @@
/**
* @file bsp_mqs.c
* @brief BSP MQS: SAI1 TX + eDMA + MQS для MIMXRT1052CVJ5B.
*
* Тактирование:
* SAI1_CLK_ROOT = SysPLL × (18/27) / (SAI1_CLK_PRED+1=4) / (SAI1_CLK_PODF+1=2)
* 63 529 411 Гц (BOARD_BOOTCLOCKRUN_SAI1_CLK_ROOT)
* Bit clock = 44100 × 16 × 2 = 1 411 200 Гц
* MCLK делитель = 63 529 411 / 1 411 200 45.0 (погрешность ~0.5 %)
*
* MQS oversample = 32, уже выставлен в BOARD_BootClockRUN() через
* IOMUXC_MQSConfig(IOMUXC_GPR, kIOMUXC_MqsPwmOverSampleRate32, 0).
*
* Пин: GPIO_AD_B0_04 MQS_RIGHT замультиплексирован в BOARD_InitPins().
*
* eDMA: DMA0 канал 0, DMAMUX source kDmaRequestMuxSai1Tx.
* Канал 0 зарезервирован за bsp_mqs. Прочие модули каналы 1+.
*
* SAI API (SDK 2.4.7 / fsl_sai.h, fsl_sai_edma.h 2.7.3):
* Конфигурация через sai_transceiver_t:
* SAI_GetClassicI2SConfig() SAI_TxSetConfig() SAI_TxSetBitClockRate()
* eDMA:
* SAI_TransferTxCreateHandleEDMA() SAI_TransferTxSetConfigEDMA()
* FIFO watermark: FSL_FEATURE_SAI_FIFO_COUNTn(x) макрос с аргументом
* экземпляра; требует #include "MIMXRT1052_features.h".
* Сброс: SAI_TxReset() (SAI_TxSoftwareReset отсутствует в этой версии).
*/
#include "bsp/mqs.h"
#include "MIMXRT1052_features.h"
#include "clock_config.h"
#include "fsl_clock.h"
#include "fsl_dmamux.h"
#include "fsl_edma.h"
#include "fsl_iomuxc.h"
#include "fsl_sai.h"
#include "fsl_sai_edma.h"
#include <string.h>
/* --------------------------------------------------------------------------
* Конфигурация периферии
* ----------------------------------------------------------------------- */
#define MQS_SAI_BASE SAI3
#define MQS_SAI_CLOCK_GATE kCLOCK_Sai3
#define MQS_SAI_CLK_FREQ BOARD_BOOTCLOCKRUN_SAI3_CLK_ROOT
/** eDMA канал, выделенный под SAI1 TX. */
#define MQS_DMA_CHANNEL (0U)
/** DMAMUX запрос для SAI1 TX. */
#define MQS_DMAMUX_SOURCE kDmaRequestMuxSai3Tx
/** Приоритет прерывания DMA (ниже USB = 3, выше нормальных задач). */
#define MQS_DMA_IRQ_PRIORITY (5U)
#define MQS_HMCLK_GATE kCLOCK_Mqs
/**
* FIFO watermark половина глубины FIFO SAI1.
* FSL_FEATURE_SAI_FIFO_COUNTn(x) принимает экземпляр SAI и возвращает
* глубину FIFO в словах (32 для RT1052). Деление на 2 даёт оптимальную
* латентность DMA: запрос формируется когда в FIFO остаётся место для
* половины буфера.
*/
#define MQS_SAI_FIFO_WATERMARK \
((uint8_t) ((uint8_t) FSL_FEATURE_SAI_FIFO_COUNTn(MQS_SAI_BASE) / 2U))
/* --------------------------------------------------------------------------
* Внутреннее состояние
* ----------------------------------------------------------------------- */
static bool g_s_initialized = false;
static volatile bool g_s_dma_done = false;
static volatile bool g_s_busy = false;
static bsp_mqs_done_cb_t g_s_user_cb = NULL;
static void *g_s_user_data = NULL;
/*
* Handles в некэшируемой секции необязательны (не DMA-буферы), но
* выравнивание по 4 байта обязательно для SDK.
*/
AT_NONCACHEABLE_SECTION_ALIGN(static edma_handle_t s_dma_handle, 4U);
AT_NONCACHEABLE_SECTION_ALIGN(static sai_edma_handle_t s_sai_tx_handle, 4U);
/* --------------------------------------------------------------------------
* DMA колбэк (ISR-контекст)
* ----------------------------------------------------------------------- */
static void mqs_edma_callback(I2S_Type *p_base, sai_edma_handle_t *p_handle, status_t status,
void *p_user_data)
{
(void) p_base;
(void) p_handle;
(void) status;
(void) p_user_data;
g_s_busy = false;
g_s_dma_done = true;
if (g_s_user_cb != NULL)
{
g_s_user_cb(g_s_user_data);
}
}
/* --------------------------------------------------------------------------
* Публичный API
* ----------------------------------------------------------------------- */
bsp_status_t bsp_mqs_init(void)
{
if (g_s_initialized)
{
return BSP_OK;
}
/* --- Тактирование SAI1 --- */
CLOCK_EnableClock(MQS_SAI_CLOCK_GATE);
/* --- Тактирование MQS (CCGR0[CG2]) — без него MQS не забирает данные из
* SAI FIFO и SAI_WriteBlocking зависает навсегда. --- */
CLOCK_EnableClock(kCLOCK_Mqs);
/* --- MQS: сброс → включение.
* Oversample ×32 уже выставлен в BOARD_BootClockRUN(),
* повторный вызов IOMUXC_MQSConfig() не нужен. --- */
IOMUXC_MQSEnterSoftwareReset(IOMUXC_GPR, true);
IOMUXC_MQSEnterSoftwareReset(IOMUXC_GPR, false);
IOMUXC_MQSEnable(IOMUXC_GPR, true);
/* --- SAI1: базовая инициализация (снимает reset, включает clock gate) --- */
SAI_Init(MQS_SAI_BASE);
/* --- SAI1 TX: классический I2S, master, 16 бит, стерео, канал 0.
* SAI_GetClassicI2SConfig() заполняет sai_transceiver_t значениями по
* умолчанию для стандартного I2S. Затем корректируем watermark и
* sync mode (async TX не зависит от RX). --- */
sai_transceiver_t sai_cfg;
SAI_GetLeftJustifiedConfig(&sai_cfg, kSAI_WordWidth16bits, kSAI_Stereo,
(uint32_t) kSAI_Channel0Mask);
sai_cfg.syncMode = kSAI_ModeAsync;
sai_cfg.fifo.fifoWatermark = MQS_SAI_FIFO_WATERMARK;
sai_cfg.startChannel = 0;
/* Явно задать источник bit clock — SAI1_CLK_ROOT (Mux делитель).
* Default после SAI_GetClassicI2SConfig может быть BusClock (IPG). */
sai_cfg.bitClock.bclkSource = kSAI_BclkSourceMclkDiv;
SAI_TxSetConfig(MQS_SAI_BASE, &sai_cfg);
/* --- Bit clock rate: вычисляется как sourceClk / (sampleRate * bitWidth * channels).
* Функция void ошибки не возвращает, делитель рассчитывается аппаратно. --- */
SAI_TxSetBitClockRate(MQS_SAI_BASE, (uint32_t) MQS_SAI_CLK_FREQ,
(uint32_t) kSAI_SampleRate44100Hz, (uint32_t) kSAI_WordWidth16bits,
BSP_MQS_CHANNELS);
/* --- eDMA --- */
edma_config_t dma_cfg;
EDMA_GetDefaultConfig(&dma_cfg);
EDMA_Init(DMA0, &dma_cfg);
EDMA_CreateHandle(&s_dma_handle, DMA0, MQS_DMA_CHANNEL);
/* --- DMAMUX: канал 0 → SAI1 TX --- */
DMAMUX_Init(DMAMUX);
DMAMUX_SetSource(DMAMUX, MQS_DMA_CHANNEL, (uint8_t) MQS_DMAMUX_SOURCE);
DMAMUX_EnableChannel(DMAMUX, MQS_DMA_CHANNEL);
/* --- SAI eDMA handle + конфигурация.
* SAI_TransferTxSetConfigEDMA() void, настраивает DMA-дескрипторы
* (размер minor loop, адрес FIFO) на основе sai_transceiver_t. --- */
SAI_TransferTxCreateHandleEDMA(MQS_SAI_BASE, &s_sai_tx_handle, mqs_edma_callback, NULL,
&s_dma_handle);
SAI_TransferTxSetConfigEDMA(MQS_SAI_BASE, &s_sai_tx_handle, &sai_cfg);
/* Включить SAI TX — без этого FIFO не дренируется даже в polling-режиме.
* SAI_TransferSendEDMA() включает его снова если MCUX_SDK_SAI_EDMA_TX_ENABLE_INTERNAL=1,
* но для корректной работы FIFO TX должен быть активен сразу после init. */
SAI_TxEnable(MQS_SAI_BASE, true);
NVIC_SetPriority(DMA0_DMA16_IRQn, MQS_DMA_IRQ_PRIORITY);
g_s_busy = false;
g_s_dma_done = false;
g_s_initialized = true;
return BSP_OK;
}
void bsp_mqs_deinit(void)
{
if (!g_s_initialized)
{
return;
}
SAI_TransferTerminateSendEDMA(MQS_SAI_BASE, &s_sai_tx_handle);
/* SAI_TxReset() — сброс logic + FIFO (аналог kSAI_ResetAll).
* SAI_TxSoftwareReset() отсутствует в данной версии SDK. */
SAI_TxReset(MQS_SAI_BASE);
IOMUXC_MQSEnable(IOMUXC_GPR, false);
CLOCK_DisableClock(MQS_SAI_CLOCK_GATE);
CLOCK_DisableClock(kCLOCK_Mqs);
g_s_busy = false;
g_s_dma_done = false;
g_s_user_cb = NULL;
g_s_user_data = NULL;
g_s_initialized = false;
}
bsp_status_t bsp_mqs_play(const int16_t *p_buf, size_t n_frames, bsp_mqs_done_cb_t p_cb,
void *p_user)
{
if ((p_buf == NULL) || (n_frames == 0U))
{
return BSP_ERR_INVALID;
}
if (g_s_busy)
{
return BSP_ERR_BUSY;
}
/* Очищаем возможный Underrun (FEF) от предыдущего проигрывания и сбрасываем FIFO */
SAI3->TCSR |= I2S_TCSR_FEF_MASK | I2S_TCSR_FR_MASK;
g_s_user_cb = p_cb;
g_s_user_data = p_user;
g_s_dma_done = false;
g_s_busy = true;
sai_transfer_t xfer;
/* p_buf — const int16_t*; SDK ожидает uint8_t*.
* Cast через uintptr_t: MISRA-compliant ptrintptr. */
xfer.data = (uint8_t *) (uintptr_t) p_buf;
xfer.dataSize = n_frames * (size_t) BSP_MQS_BYTES_PER_FRAME;
status_t status = SAI_TransferSendEDMA(MQS_SAI_BASE, &s_sai_tx_handle, &xfer);
if (status != kStatus_Success)
{
g_s_busy = false;
return BSP_ERR_HW;
}
return BSP_OK;
}
bsp_status_t bsp_mqs_play_blocking(const int16_t *p_buf, size_t n_frames)
{
bsp_status_t status = bsp_mqs_play(p_buf, n_frames, NULL, NULL);
if (status != BSP_OK)
{
return status;
}
/*
* Polling-ожидание завершения DMA.
* Флаг s_dma_done взводится из ISR (mqs_edma_callback).
* USB keepalive выполняется в вызывающем тест-коде (test_mqs_run).
*/
while (!g_s_dma_done)
{
/* bare-metal: явное ожидание ISR */
}
return BSP_OK;
}
void bsp_mqs_stop(void)
{
if (!g_s_busy)
{
return;
}
SAI_TransferTerminateSendEDMA(MQS_SAI_BASE, &s_sai_tx_handle);
g_s_busy = false;
g_s_dma_done = false;
/* Колбэк НЕ вызывается: явная остановка — ответственность вызывающего. */
}
bool bsp_mqs_is_busy(void)
{
return g_s_busy;
}

141
bsp/mqs/src/mqs_amp.c Normal file
View file

@ -0,0 +1,141 @@
/**
* @file bsp_mqs_amp.c
* @brief BSP: управление усилителем звука LM4875M через FlexPWM4 SM0 PWM_A.
*
* Схема:
* GPIO_AD_B1_08 (PWM4_A, SM0) R56 (1K) LM358 +IN1 LM4875M DC_VOL
* DC_VOL управляет коэффициентом усиления LM4875M.
* HP_SEN LM4875M подтянут к GND включается автоматически при наличии
* аудио-сигнала на входе (MQS_RIGHT через RC-фильтр SOUND_OUT).
*
* Управление громкостью:
* PWM4 SM0 PWM_A, частота 16 кГц, центрально-симметричный режим.
* duty 0% DC_VOL 0 В усиление минимально (тишина).
* duty 50% DC_VOL 2.5 В номинальная громкость.
* duty 100% DC_VOL 5 В максимальное усиление.
*
* Fault-вход PWM4:
* XBARA1: kXBARA1_InputLogicHigh kXBARA1_OutputFlexpwm4Fault0.
* Fault сконфигурирован как "no fault" PWM работает без аппаратного
* отключения. Это повторяет конфигурацию из оригинального timers.c.
*
* Тактирование:
* IPG clock = AHB/4 = 600/4 = 150 МГц.
* PWM prescaler = /16 PWM clock = 9.375 МГц.
* Fpwm = 16000 Гц (центрально-симметричный режим).
*/
#include "bsp/mqs.h"
#include "clock_config.h"
#include "fsl_clock.h"
#include "fsl_pwm.h"
#include "fsl_xbara.h"
/* --------------------------------------------------------------------------
* Конфигурация
* ----------------------------------------------------------------------- */
#define AMP_PWM_BASE PWM4
#define AMP_PWM_SUBMODULE kPWM_Module_0
#define AMP_PWM_CHANNEL kPWM_PwmA
#define AMP_PWM_MODE kPWM_SignedCenterAligned
#define AMP_PWM_FREQ_HZ (16000U)
/** Номинальный duty cycle при bsp_mqs_amp_init() — 50%. */
#define AMP_DEFAULT_DUTY (50U)
/** IPG clock = 150 МГц (AHB/4). */
#define AMP_PWM_SRC_CLK_HZ (BOARD_BOOTCLOCKRUN_IPG_CLK_ROOT)
/* --------------------------------------------------------------------------
* Публичный API
* ----------------------------------------------------------------------- */
bsp_status_t bsp_mqs_amp_init(void)
{
/* --- XBARA1: подать логическую единицу на Fault0 PWM4.
* Это предотвращает аппаратное отключение PWM при старте. --- */
XBARA_Init(XBARA1);
XBARA_SetSignalsConnection(XBARA1, kXBARA1_InputLogicHigh, kXBARA1_OutputFlexpwm4Fault0);
/* --- PWM4 SM0: базовая конфигурация --- */
pwm_config_t pwm_cfg;
PWM_GetDefaultConfig(&pwm_cfg);
pwm_cfg.clockSource = kPWM_BusClock;
pwm_cfg.prescale = kPWM_Prescale_Divide_16;
pwm_cfg.pairOperation = kPWM_Independent;
pwm_cfg.initializationControl = kPWM_Initialize_LocalSync;
pwm_cfg.reloadLogic = kPWM_ReloadImmediate;
pwm_cfg.reloadSelect = kPWM_LocalReload;
pwm_cfg.reloadFrequency = kPWM_LoadEveryOportunity;
pwm_cfg.forceTrigger = kPWM_Force_Local;
if (PWM_Init(AMP_PWM_BASE, AMP_PWM_SUBMODULE, &pwm_cfg) != kStatus_Success)
{
return BSP_ERR_HW;
}
/* --- Fault-фильтр и fault-конфигурация (no fault active) --- */
const pwm_fault_input_filter_param_t FAULT_FILTER = {
.faultFilterPeriod = 1U,
.faultFilterCount = 3U,
.faultGlitchStretch = false,
};
PWM_SetupFaultInputFilter(AMP_PWM_BASE, &FAULT_FILTER);
const pwm_fault_param_t FAULT_CFG = {
.faultClearingMode = kPWM_Automatic,
.faultLevel = false,
.enableCombinationalPath = false,
.recoverMode = kPWM_NoRecovery,
};
PWM_SetupFaults(AMP_PWM_BASE, kPWM_Fault_0, &FAULT_CFG);
PWM_SetupFaults(AMP_PWM_BASE, kPWM_Fault_1, &FAULT_CFG);
PWM_SetupFaults(AMP_PWM_BASE, kPWM_Fault_2, &FAULT_CFG);
PWM_SetupFaults(AMP_PWM_BASE, kPWM_Fault_3, &FAULT_CFG);
/* --- ForceSignal: использовать нормальный PWM-сигнал --- */
PWM_SetupForceSignal(AMP_PWM_BASE, AMP_PWM_SUBMODULE, AMP_PWM_CHANNEL, kPWM_UsePwm);
/* --- PWM-сигнал: 16 кГц, центрально-симметричный, duty 50% --- */
const pwm_signal_param_t PWM_SIGNAL = {
.pwmChannel = AMP_PWM_CHANNEL,
.dutyCyclePercent = AMP_DEFAULT_DUTY,
.level = kPWM_HighTrue,
.faultState = kPWM_PwmFaultState0,
.deadtimeValue = 0U,
};
if (PWM_SetupPwm(AMP_PWM_BASE, AMP_PWM_SUBMODULE, &PWM_SIGNAL, 1U, AMP_PWM_MODE,
AMP_PWM_FREQ_HZ, (uint32_t) AMP_PWM_SRC_CLK_HZ) != kStatus_Success)
{
return BSP_ERR_HW;
}
/* --- Применить и запустить --- */
PWM_SetPwmLdok(AMP_PWM_BASE, (uint8_t) kPWM_Control_Module_0, true);
PWM_StartTimer(AMP_PWM_BASE, (uint8_t) kPWM_Control_Module_0);
return BSP_OK;
}
void bsp_mqs_amp_set_volume(uint8_t percent)
{
if (percent > 100U)
{
percent = 100U;
}
PWM_UpdatePwmDutycycle(AMP_PWM_BASE, AMP_PWM_SUBMODULE, AMP_PWM_CHANNEL, AMP_PWM_MODE, percent);
PWM_SetPwmLdok(AMP_PWM_BASE, (uint8_t) kPWM_Control_Module_0, true);
}
void bsp_mqs_amp_deinit(void)
{
/* Установить duty 0% перед остановкой — плавное выключение. */
PWM_UpdatePwmDutycycle(AMP_PWM_BASE, AMP_PWM_SUBMODULE, AMP_PWM_CHANNEL, AMP_PWM_MODE, 0U);
PWM_SetPwmLdok(AMP_PWM_BASE, (uint8_t) kPWM_Control_Module_0, true);
PWM_StopTimer(AMP_PWM_BASE, (uint8_t) kPWM_Control_Module_0);
PWM_Deinit(AMP_PWM_BASE, AMP_PWM_SUBMODULE);
}

View file

@ -14,6 +14,7 @@ add_executable(
src/tests/test_opto.c src/tests/test_opto.c
src/tests/test_sdram.c src/tests/test_sdram.c
src/tests/test_can.c src/tests/test_can.c
src/tests/test_mqs.c
src/tests/test_qspi.c src/tests/test_qspi.c
src/tests/test_usd.c src/tests/test_usd.c
src/tests/test_display.c src/tests/test_display.c
@ -49,7 +50,9 @@ target_link_libraries(
bsp_usb_cdc bsp_usb_cdc
bsp_sdram bsp_sdram
bsp_qspi_flash bsp_qspi_flash
bsp_uart_host
bsp_opto bsp_opto
bsp_mqs
bsp_sd bsp_sd
firmware_test_fatfs) firmware_test_fatfs)

View file

@ -1,4 +1,206 @@
/**
* @file main_mqs_test.c
* @brief Изолированный тест bsp_mqs + bsp_mqs_amp.
*
* Подменяет firmware/test/src/main.c на время отладки BSP.
* Вывод диагностики UART (MCU-Link VCOM, 115200 бод).
*
* Два режима переключаются комментарием в main():
* TEST_MODE_POLLING SAI_WriteBlocking напрямую, без DMA.
* Если звук есть SAI/MQS OK, проблема в DMA.
* Если нет проблема в SAI/MQS/усилителе.
* TEST_MODE_DMA bsp_mqs_play_blocking через eDMA.
*/
#include "board.h"
#include "bsp/led.h"
#include "bsp/mqs.h"
#include "bsp/tick.h"
#include "bsp/uart_host.h"
#include "fsl_sai.h"
#include <stdint.h>
#include <string.h>
/* --------------------------------------------------------------------------
* Выбор режима: раскомментируй один
* ----------------------------------------------------------------------- */
//#define TEST_MODE_POLLING
#define TEST_MODE_DMA
/* --------------------------------------------------------------------------
* Буфер мелодии в некэшируемой секции
* ----------------------------------------------------------------------- */
#define MQS_NOTE_SAMPLES (44100U * 2U) /* 2 с на ноту */
#define MQS_TOTAL_FRAMES (MQS_NOTE_SAMPLES * 2U) /* 2 ноты */
#define MQS_BUF_ELEMENTS (MQS_TOTAL_FRAMES * BSP_MQS_CHANNELS)
static AT_NONCACHEABLE_SECTION_ALIGN(int16_t s_melody_buf[MQS_BUF_ELEMENTS], 4U);
/* --------------------------------------------------------------------------
* Синусоида (целочисленная, LUT по четвертям)
* ----------------------------------------------------------------------- */
static int16_t sine_sample(uint32_t phase, uint32_t period)
{
static const int16_t k_lut[25] = {
0, 2998, 5944, 8788, 11479, 13970, 16212, 18162, 19784, 21043, 21910, 22369, 22404,
22005, 21170, 19898, 18199, 16084, 13567, 10670, 7416, 3831, 0, -3831, -7416,
};
uint32_t idx = (phase * 96U) / period % 96U;
uint32_t quarter = idx / 24U;
uint32_t pos = idx % 24U;
int16_t val;
switch (quarter)
{
case 0U:
val = k_lut[pos];
break;
case 1U:
val = k_lut[24U - pos];
break;
case 2U:
val = -k_lut[pos];
break;
default:
val = -k_lut[24U - pos];
break;
}
return val;
}
static void build_melody(void)
{
const uint32_t k_p_a4 = 100U; /* A4 ≈ 440 Гц */
const uint32_t k_p_e5 = 67U; /* E5 ≈ 659 Гц */
uint32_t out = 0U;
for (uint32_t i = 0U; i < MQS_NOTE_SAMPLES; i++)
{
int16_t s = sine_sample(i % k_p_a4, k_p_a4);
s_melody_buf[out++] = s; /* L */
s_melody_buf[out++] = s; /* R */
}
for (uint32_t i = 0U; i < MQS_NOTE_SAMPLES; i++)
{
int16_t s = sine_sample(i % k_p_e5, k_p_e5);
s_melody_buf[out++] = s; /* L */
s_melody_buf[out++] = s; /* R */
}
}
/* --------------------------------------------------------------------------
* Режим A: SAI polling напрямую, без DMA
*
* SAI_WriteBlocking блокирует до записи всех байт через FIFO.
* Не требует DMA вообще. Если звук есть SAI и MQS живые.
* ----------------------------------------------------------------------- */
#ifdef TEST_MODE_POLLING
static void run_test(void)
{
bsp_uart_host_write_str("[5A] Bare-metal SAI polling...\r\n");
/* 1. Глушим передатчик и отключаем запросы DMA, чтобы не мешали поллингу */
SAI3->TCSR &= ~(I2S_TCSR_TE_MASK | I2S_TCSR_BCE_MASK | I2S_TCSR_FRDE_MASK);
/* 2. Сбрасываем ошибку Underrun (FEF) и чистим FIFO (FR) */
SAI3->TCSR |= I2S_TCSR_FEF_MASK | I2S_TCSR_FR_MASK;
/* 3. Предзагружаем FIFO (закинем 16 сэмплов ДО включения) */
/* Это спасет аппаратуру от мгновенного Underrun'а при старте */
for (uint32_t i = 0; i < 16; i++)
{
SAI3->TDR[0] = s_melody_buf[i];
}
/* 4. Включаем передатчик и генерацию Bit Clock */
SAI3->TCSR |= (I2S_TCSR_TE_MASK | I2S_TCSR_BCE_MASK);
/* 5. Качаем остальной буфер вручную */
for (uint32_t i = 16; i < MQS_BUF_ELEMENTS; i++)
{
/* Ждем, пока в FIFO появится свободное место (FWF == 1) */
while ((SAI3->TCSR & I2S_TCSR_FWF_MASK) == 0)
{
/* Если всё-таки поймали опустошение - перезапускаем TX на лету */
if (SAI3->TCSR & I2S_TCSR_FEF_MASK)
{
SAI3->TCSR |= I2S_TCSR_FEF_MASK; /* Сброс ошибки */
SAI3->TCSR |= I2S_TCSR_TE_MASK | I2S_TCSR_BCE_MASK; /* Рестарт TX */
}
}
/* Пишем следующий сэмпл */
SAI3->TDR[0] = s_melody_buf[i];
}
/* 6. Дожидаемся, пока уйдут остатки из FIFO, и выключаем */
while (SAI3->TCSR & I2S_TCSR_FWF_MASK)
{
}
SAI3->TCSR &= ~(I2S_TCSR_TE_MASK | I2S_TCSR_BCE_MASK);
bsp_uart_host_write_str("[5A] Done.\r\n");
}
#endif
/* --------------------------------------------------------------------------
* Режим B: DMA через bsp_mqs_play_blocking
* ----------------------------------------------------------------------- */
#ifdef TEST_MODE_DMA
static void run_test(void)
{
bsp_uart_host_write_str("[5B] DMA play, ~4s...\r\n");
bsp_status_t st = bsp_mqs_play_blocking(s_melody_buf, MQS_TOTAL_FRAMES);
bsp_uart_host_write_str(st == BSP_OK ? "[5B] OK\r\n" : "[5B] FAIL\r\n");
}
#endif
/* --------------------------------------------------------------------------
* main
* ----------------------------------------------------------------------- */
int main(void)
{
board_hw_init();
bsp_tick_init();
bsp_led_init();
(void) bsp_uart_host_init(115200U);
bsp_led_on(LED_HEARTBEAT);
bsp_uart_host_write_str("\r\n=== MQS BSP TEST ===\r\n");
/* Шаг 1 — усилитель */
bsp_uart_host_write_str("[1] amp_init...\r\n");
bsp_status_t st = bsp_mqs_amp_init();
bsp_uart_host_write_str(st == BSP_OK ? "[1] OK\r\n" : "[1] FAIL\r\n");
/* Шаг 2 — SAI + DMA + MQS */
bsp_uart_host_write_str("[2] mqs_init...\r\n");
st = bsp_mqs_init();
bsp_uart_host_write_str(st == BSP_OK ? "[2] OK\r\n" : "[2] FAIL\r\n");
/* Шаг 3 — генерация буфера */
bsp_uart_host_write_str("[3] build_melody...\r\n");
build_melody();
bsp_uart_host_write_str("[3] done.\r\n");
/* Основной цикл */
for (;;)
{
bsp_led_toggle(LED_HEARTBEAT);
run_test();
bsp_uart_host_write_str("[pause] 3s\r\n");
bsp_delay(3000U);
}
return 0;
}
#if 0
/** /**
* @file main.c * @file main.c
* @brief firmware_test точка входа. * @brief firmware_test точка входа.
@ -65,3 +267,4 @@ int main(void)
test_runner_process(); test_runner_process();
} }
} }
#endif

View file

@ -32,11 +32,12 @@ extern const test_module_t K_TEST_DISPLAY;
extern const test_module_t K_TEST_BUTTONS; extern const test_module_t K_TEST_BUTTONS;
extern const test_module_t K_TEST_OPTO; extern const test_module_t K_TEST_OPTO;
extern const test_module_t K_TEST_CAN; extern const test_module_t K_TEST_CAN;
extern const test_module_t K_TEST_MQS;
static const test_module_t *const k_registry[] = { static const test_module_t *const k_registry[] = {
&K_TEST_SDRAM, &K_TEST_QSPI, &K_TEST_USD, &K_TEST_DISPLAY, &K_TEST_SDRAM, &K_TEST_QSPI, &K_TEST_USD, &K_TEST_DISPLAY,
&K_TEST_BUTTONS, &K_TEST_OPTO, &K_TEST_CAN, &K_TEST_BUTTONS, &K_TEST_OPTO, &K_TEST_CAN, &K_TEST_MQS,
}; };
#define REGISTRY_SIZE (sizeof(k_registry) / sizeof(k_registry[0])) #define REGISTRY_SIZE (sizeof(k_registry) / sizeof(k_registry[0]))

View file

@ -0,0 +1,223 @@
/**
* @file test_mqs.c
* @brief Тест MQS: воспроизведение тестового тона через SAI1 + eDMA + MQS.
*
* Алгоритм:
* 1. init() bsp_mqs_init(), генерация мелодии в s_melody_buf.
* 2. run() воспроизвести мелодию (~4 с) с USB keepalive в цикле,
* затем confirm_request("mqs_tone") оператор подтверждает.
* 3. deinit() bsp_mqs_stop(), bsp_mqs_deinit().
*
* Мелодия: стерео PCM16 44100 Гц, две ноты (A4/E5) по 2 с каждая.
* Буфер статический глобальный в некэшируемой секции (OCRAM NonCacheable).
* L == R (монофонический выход на плате).
*
* Протокол:
* confirm_request("mqs_tone", "Слышен звуковой сигнал?", 15000)
* confirm("mqs_tone", true/false)
* test_result pass/fail/skip
*/
#include "bsp/mqs.h"
#include "bsp/tick.h"
#include "bsp/usb_cdc.h"
#include "fsl_common.h"
#include "test_module.h"
#include "test_runner.h"
#include <stddef.h>
#include <stdint.h>
#include <string.h>
/* --------------------------------------------------------------------------
* Буфер мелодии
* ----------------------------------------------------------------------- */
/*
* Две ноты, по 2 с каждая: A4 (440 Гц) + E5 (659 Гц).
* Моно-сэмплов: 44100 × 2 = 88200 на ноту.
* Стерео-фреймов = моно-сэмплов (каждый L дублируется в R).
* int16_t на фрейм: 2 (L + R).
* Итого: 88200 × 2 × 2 = 352800 int16_t = 705 600 байт.
*
* DMA-буфер объявлен через AT_NONCACHEABLE_SECTION_ALIGN (паттерн из test_display.c).
*/
#define MQS_NOTE_SAMPLES (44100U * 2U)
#define MQS_TOTAL_MONO_SAMPLES (MQS_NOTE_SAMPLES * 2U)
#define MQS_TOTAL_FRAMES MQS_TOTAL_MONO_SAMPLES
#define MQS_BUF_ELEMENTS (MQS_TOTAL_FRAMES * BSP_MQS_CHANNELS)
/*
* DMA-буфер мелодии в некэшируемой секции OCRAM.
* static передаётся внутрь var-аргумента макроса единственный валидный
* способ, так как макрос раскрывается как:
* __attribute__((section(...))) var __attribute__((aligned(N)))
* Паттерн идентичен test_display.c (g_s_framebuf).
*/
static AT_NONCACHEABLE_SECTION_ALIGN(int16_t s_melody_buf[MQS_BUF_ELEMENTS], 4U);
static bool g_s_melody_ready = false;
/* --------------------------------------------------------------------------
* Генерация мелодии (целочисленная синусоида)
* ----------------------------------------------------------------------- */
/*
* Таблица синуса: 96 точек на период (шаг π/48).
* Амплитуда 22937 0.70 × INT16_MAX запас от клиппинга на MQS.
* Генерируется по четвертям (таблица хранит только одну четверть).
*/
static int16_t sine_sample(uint32_t phase, uint32_t period)
{
static const int16_t K_SIN_LUT[25] = {
0, 2998, 5944, 8788, 11479, 13970, 16212, 18162, 19784, 21043, 21910, 22369, 22404,
22005, 21170, 19898, 18199, 16084, 13567, 10670, 7416, 3831, 0, -3831, -7416,
};
uint32_t idx = (phase * 96U) / period % 96U;
uint32_t quarter = idx / 24U;
uint32_t pos = idx % 24U;
int16_t val;
switch (quarter)
{
case 0U:
val = K_SIN_LUT[pos];
break;
case 1U:
val = K_SIN_LUT[24U - pos];
break;
case 2U:
val = -K_SIN_LUT[pos];
break;
default:
val = -K_SIN_LUT[24U - pos];
break;
}
return val;
}
static void mqs_build_melody(void)
{
if (g_s_melody_ready)
{
return;
}
/* A4 = 440 Гц → период ≈ 100 сэмплов при 44100 Гц */
const uint32_t K_PERIOD_A4 = 100U;
/* E5 = 659 Гц → период ≈ 67 сэмплов при 44100 Гц */
const uint32_t K_PERIOD_E5 = 67U;
uint32_t out = 0U;
for (uint32_t i = 0U; i < MQS_NOTE_SAMPLES; i++)
{
int16_t s = sine_sample(i % K_PERIOD_A4, K_PERIOD_A4);
s_melody_buf[out++] = s; /* L */
s_melody_buf[out++] = s; /* R == L */
}
for (uint32_t i = 0U; i < MQS_NOTE_SAMPLES; i++)
{
int16_t s = sine_sample(i % K_PERIOD_E5, K_PERIOD_E5);
s_melody_buf[out++] = s; /* L */
s_melody_buf[out++] = s; /* R == L */
}
g_s_melody_ready = true;
}
/* --------------------------------------------------------------------------
* Воспроизведение с USB keepalive
* ----------------------------------------------------------------------- */
/*
* Запускаем bsp_mqs_play() (не blocking), чтобы параллельно вызывать
* bsp_usb_cdc_poll(). Без этого USB стек голодает за ~4 с воспроизведения
* (keepalive-порог ~4 КБ переданных данных).
*/
static bsp_status_t mqs_play_with_poll(void)
{
bsp_status_t status = bsp_mqs_play(s_melody_buf, MQS_TOTAL_FRAMES, NULL, NULL);
if (status != BSP_OK)
{
return status;
}
while (bsp_mqs_is_busy())
{
bsp_usb_cdc_poll();
}
return BSP_OK;
}
/* --------------------------------------------------------------------------
* test_module_t callbacks
* ----------------------------------------------------------------------- */
static void test_mqs_init(void)
{
mqs_build_melody();
(void) bsp_mqs_init();
(void) bsp_mqs_amp_init();
}
static test_result_t test_mqs_run(void)
{
bsp_status_t play_st = mqs_play_with_poll();
if (play_st != BSP_OK)
{
return (test_result_t){
.status = TEST_STATUS_FAIL,
.detail = "mqs play error",
};
}
/* Запрашиваем подтверждение оператора.
* API: bool test_runner_wait_confirm(const confirm_params_t *p_params)
* Возвращает true если оператор подтвердил, false при отказе или таймауте.
* Таймаут детектируется отдельно через флаг в confirm_params_t. */
const confirm_params_t PARAMS = {
.id = "mqs_tone",
.prompt = "Have you heard a tone?",
.timeout_ms = 15000U,
};
bool confirmed = test_runner_wait_confirm(&PARAMS);
if (!confirmed)
{
/* Различаем таймаут и явный отказ через поле last_confirm_timed_out
* если оно есть в API, иначе унифицируем как fail. */
return (test_result_t){
.status = TEST_STATUS_FAIL,
.detail = "operator: no sound",
};
}
return (test_result_t){ .status = TEST_STATUS_PASS, .detail = "" };
}
static void test_mqs_deinit(void)
{
bsp_mqs_stop();
bsp_mqs_amp_deinit();
bsp_mqs_deinit();
}
/* --------------------------------------------------------------------------
* Дескриптор модуля
* ----------------------------------------------------------------------- */
const test_module_t K_TEST_MQS = {
.id = "mqs",
.name = "MQS Audio Out",
.critical = false,
.requires_hil = false,
.pre_confirm_prompt = NULL,
.init = test_mqs_init,
.run = test_mqs_run,
.deinit = test_mqs_deinit,
};

View file

@ -57,6 +57,12 @@ add_sdk_driver(pwm fsl_pwm.c)
add_sdk_driver(adc fsl_adc.c) add_sdk_driver(adc fsl_adc.c)
add_sdk_driver(elcdif fsl_elcdif.c) add_sdk_driver(elcdif fsl_elcdif.c)
add_sdk_driver(cache fsl_cache.c) add_sdk_driver(cache fsl_cache.c)
add_sdk_driver(sai fsl_sai.c)
add_sdk_driver(sai_edma fsl_sai_edma.c)
add_sdk_driver(edma fsl_edma.c)
add_sdk_driver(dmamux fsl_dmamux.c)
add_sdk_driver(xbara fsl_xbara.c)
add_sdk_driver(xbarb fsl_xbarb.c)
# Драйверы которые зависят от clock # Драйверы которые зависят от clock
target_link_libraries(sdk_lpuart PUBLIC sdk_clock) target_link_libraries(sdk_lpuart PUBLIC sdk_clock)
@ -66,7 +72,10 @@ target_link_libraries(sdk_lpi2c PUBLIC sdk_clock)
target_link_libraries(sdk_pwm PUBLIC sdk_clock) target_link_libraries(sdk_pwm PUBLIC sdk_clock)
target_link_libraries(sdk_adc PUBLIC sdk_clock) target_link_libraries(sdk_adc PUBLIC sdk_clock)
target_link_libraries(sdk_elcdif PUBLIC sdk_clock) target_link_libraries(sdk_elcdif PUBLIC sdk_clock)
target_link_libraries(sdk_sai PUBLIC sdk_clock)
target_link_libraries(sdk_sai_edma PUBLIC sdk_sai sdk_edma)
target_link_libraries(sdk_edma PUBLIC sdk_common)
target_link_libraries(sdk_xbara PUBLIC sdk_clock)
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# SEMC и FlexSPI — инициализируются через DCD и FDCB, драйверы нужны только если # SEMC и FlexSPI — инициализируются через DCD и FDCB, драйверы нужны только если
# обращаешься к ним явно из кода # обращаешься к ним явно из кода