; Copyright (c) 2023, Texas Instruments Incorporated ; All rights reserved. ; ; Redistribution and use in source and binary forms, with or without ; modification, are permitted provided that the following conditions ; are met: ; ; * Redistributions of source code must retain the above copyright ; notice, this list of conditions and the following disclaimer. ; ; * Redistributions in binary form must reproduce the above copyright ; notice, this list of conditions and the following disclaimer in the ; documentation and/or other materials provided with the distribution. ; ; * Neither the name of Texas Instruments Incorporated nor the names of ; its contributors may be used to endorse or promote products derived ; from this software without specific prior written permission. ; ; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, ; THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR ; CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, ; EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, ; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; ; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR ; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, ; EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ; ; file: sdfm.asm ; ; ;********************************** includes ************************************** .cdecls C,NOLIST %{ #include "icssg_sdfm.h" %} .include "sdfm.h" .include "sdfm_macros.h" .include "firmware_version.h" ;*********************************************************************************** ;********************************************* defines ******************************************* ; Compile-time Host event for SDFM samples available ; R31 event interface mapping, add pru_r31_vec_valid to system event number, + 1<<5 .if $isdefed("SDFM_PRU_CORE") TRIGGER_HOST_SDFM_IRQ .set PRU_TRIGGER_HOST_SDFM_EVT + 16 .elseif $isdefed("SDFM_RTU_CORE") TRIGGER_HOST_SDFM_IRQ .set RTU_TRIGGER_HOST_SDFM_EVT + 16 .elseif $isdefed("SDFM_TXPRU_CORE") TRIGGER_HOST_SDFM_IRQ .set TXPRU_TRIGGER_HOST_SDFM_EVT + 16 .endif ;SPAD Bank for SD Ch context storage BANK_CTXT_NC .set BANK0 ;differentiator state located in BANK locations 9-17 NUM_REGS_DIFF_STATE .set 9 ; Number of PRU registers for differentiator state OUT_SAMP_MASK .set 0x0FFFFFFF ; 28-bit mask applied to Integrator & Differentiator output ;Required sample for stable NC sample = NC_SAMP_CNT - 1 NC_SAMP_CNT .set 4 ;*************************************************************************************************** ;--------------------------------------Unsed Registers-------------------------------------; ;registers R20 - R24 ;R20: contain address of NC local output ;R21; output mask ;R22.w0 channel ID ;R24 PRUx CFG base address ;-------------------------------------------------------------------------------------------; ; local interleaved NC output sample buffer OUT_SAMP_BUF: .usect ".outSamps", ICSSG_NUM_SD_CH_FW*4, 4 .retain ".outSamps" .retainrefs ".outSamps" .def SDFM_ENTRY ; global entry point .ref dbg_setup_pinmux .sect ".text" .retain ".text" .retainrefs ".text" ;*************************** ; *ENTRY POINT* ;*************************** SDFM_ENTRY: ; Clear registers R0-R30 ZERO &R0, 124 ;set DMEM base poiter to FW configuration registers LDI SDFM_CFG_BASE_PTR_REG, ICSSG_SDFM_CTRL_BASE LDI32 TEMP_REG0, ICSS_FIRMWARE_RELEASE_1 LDI32 TEMP_REG1, ICSS_FIRMWARE_RELEASE_2 SBBO &TEMP_REG0, SDFM_CFG_BASE_PTR_REG, SDFM_FIRMWARE_VERSION_OFFSET, 8 ; Disable Task Manager ;.word 0x32000000 M_PRU_TM_DISABLE ; Clear Task Manager status which is sticky after debug halt LDI TEMP_REG0.w0, 0x0fff .if $isdefed("SDFM_TXPRU_CORE") SBCO &TEMP_REG0.w0, C28, 0, 2 .else SBCO &TEMP_REG0.w0, CT_PRU_ICSSG_TM, 0, 2 .endif XIN TM_YIELD_XID, &R0.b3,1 LDI TEMP_REG0.w0, 0 .if $isdefed("SDFM_TXPRU_CORE") SBCO &TEMP_REG0.w0, C28, 0, 2 .else SBCO &TEMP_REG0.w0, CT_PRU_ICSSG_TM, 0, 2 .endif ;Write C24 block index for local PRU DMEM M_WRITE_C24_BLK_INDEX C24_BLK_INDEX_FW_REGS_VAL PHASE_DELAY_CAL: ;check phase delay measurment active LBBO &TEMP_REG0.b0, SDFM_CFG_BASE_PTR_REG, SDFM_CFG_SD_EN_PHASE_DELAY, 1 QBBC SKIP_PHASE_DELAY_CAL, TEMP_REG0.b0, 0 JAL RET_ADDR_REG, SDFM_CLOCK_PHASE_COMPENSATION ;acknowledge CLR TEMP_REG0, TEMP_REG0, 0 SBBO &TEMP_REG0.b0, SDFM_CFG_BASE_PTR_REG, SDFM_CFG_SD_EN_PHASE_DELAY, 1 SKIP_PHASE_DELAY_CAL: ; ; Check SDFM global enable & set SDFM global enable acknowledge to inform R5 core. ; If SDFM global enable not set, wait for SDFM global enable from R5. ; CHECK_SDFM_EN: ;check phase delay measurment active LBBO &TEMP_REG0.b0, SDFM_CFG_BASE_PTR_REG, SDFM_CFG_SD_EN_PHASE_DELAY, 1 QBBS PHASE_DELAY_CAL, TEMP_REG0.b0, 0 ; Check SDFM global enable LBBO &TEMP_REG0.b0, SDFM_CFG_BASE_PTR_REG, SDFM_EN_OFFSET, SDFM_EN_SZ QBBC CHECK_SDFM_EN, TEMP_REG0.b0, 0 ; If SDFM_EN not set, wait to set sdfm enable ; Set SDFM global enable acknowledge SET TEMP_REG0, TEMP_REG0, 0 ; Set SDFM_EN_ACK SBBO &TEMP_REG0.b0, SDFM_CFG_BASE_PTR_REG, SDFM_EN_ACK_OFFSET, SDFM_EN_ACK_SZ ; ; Perform initialization ; INIT_SDFM: ; Enable XIN/XOUT shifting. ; Used for context & SD state save/restore in TM tasks. LBCO &TEMP_REG0.b0, CT_PRU_ICSSG_CFG, ICSSG_CFG_SPPC, 1 .if $isdefed("SDFM_PRU_CORE") SET TEMP_REG0, TEMP_REG0, XFR_SHIFT_EN_BN ; ICSSG_SPP_REG:XFR_SHIFT_EN=1 .elseif $isdefed("SDFM_RTU_CORE") SET TEMP_REG0, TEMP_REG0, RTU_XFR_SHIFT_EN ; ICSSG_SPP_REG:RTU_XFR_SHIFT_EN=1 .endif SBCO &TEMP_REG0.b0, CT_PRU_ICSSG_CFG, ICSSG_CFG_SPPC, 1 ;Initialize Task Manager JAL RET_ADDR_REG, FN_TM_INIT ;Enable Task Manager M_PRU_TM_ENABLE .if $isdefed("SDFM_PRU_CORE") ;Initialize IEP0 JAL RET_ADDR_REG, FN_IEP0_INIT .endif .if $isdefed("SDFM_PRU_CORE") ;Initialize SD mode LDI32 TEMP_REG1, PR1_PRUn_GP_MUX_SEL_VAL< CMP4 enabled SBCO &TEMP_REG0.b0, CT_PRU_ICSSG_IEP0, ICSSG_IEP_CMP_CFG_REG, 1 ; TR0 -> ICSSG_CMP_CFG_REG Byte0 JMP RET_ADDR_REG ; ; Reset Scratchpad for NC registers ; ; Arguments: None ; FN_RESET_SDFM_STATE: LDI R0.b0, 0 ZERO &R1, 4*18 XOUT BANK_CTXT_NC, &R1, 4*18 ;clear ScratchPad registers for NC JMP RET_ADDR_REG ; ; Configure OC OSR, FD_ONE Min/Max, for SD channels ; ; Arguments: ; SDFM_CFG_BASE_PTR_REG: base address of SD Configuration registers (&IEP_CFG_EPWM_PRD) ; SD_HW_BASE_PTR_REG: base address of SD HW configuration registers (&ICSSG_PRUn_SD_CLK_SEL_REG0) ; FN_CONFIG_SD_SAMPLE_SIZE_REG: ;Load fast detect enable bits LBBO &TEMP_REG3, SDFM_CFG_BASE_PTR_REG, SDFM_CFG_SD_EN_FD_OFFSET, 1 LDI TEMP_REG0, 0 ; Load TR1.w0 <- SDFM_CFG_SD_CH_ID = ;LDI TEMP_REG1.w0, 0x210 =001100010000 LBBO &TEMP_REG1.w0, SDFM_CFG_BASE_PTR_REG, SDFM_CFG_SD_CH_ID_OFFSET, SDFM_CFG_SD_CH_ID_SZ LOOP config_osr_loop_end, ICSSG_NUM_SD_CH_FW ; loop over SD channels AND TEMP_REG2.b0, TEMP_REG1.b0, BF_SD_CH0_ID_MASK ; LS byte is ID for Ch0 QBNE SDFM_SKIP0_CH0, TEMP_REG2.b0, SD_CH0_ID ; Load TR0.b0 <- SDFM_CFG_OSR load osr from DMEM for ch0 LBBO &TEMP_REG0.b0, SDFM_CFG_BASE_PTR_REG, SDFM_CFG_CH0_OSR_OFFSET, SDFM_CFG_OSR_SZ QBBC SDFM_SKIP0_CH2, TEMP_REG3.b0, 0 ;configure fast detect one count and enable fast detect LBBO &FAST_WINDOW_REG, SDFM_CFG_BASE_PTR_REG, SDFM_CFG_CH0_FD_WD_REG_OFFSET, 1 LBBO &FAST_ONE_MIN_REG, SDFM_CFG_BASE_PTR_REG, SDFM_CFG_CH0_FD_ONE_MIN_REG_OFFSET, 1 LBBO &FAST_ONE_MAX_REG, SDFM_CFG_BASE_PTR_REG, SDFM_CFG_CH0_FD_ONE_MAX_REG_OFFSET, 1 MOV TEMP_REG0.b1, FAST_WINDOW_REG LSL TEMP_REG0.b2, FAST_ONE_MIN_REG, 3 OR TEMP_REG0.b1, TEMP_REG0.b2, TEMP_REG0.b1 LSL TEMP_REG0.b2, FAST_ONE_MAX_REG, 1 OR TEMP_REG0.b2, TEMP_REG0.b2, 0x41;clear max & min threshold hit OR TEMP_REG0.b2, TEMP_REG0.b2, 0x80;enable fast detec JMP SDFM_SKIP0_CH2 SDFM_SKIP0_CH0: QBNE SDFM_SKIP0_CH1, TEMP_REG2.b0, SD_CH1_ID ; Load TR0.b0 <- SDFM_CFG_OSR load osr from DMEM for ch1 LBBO &TEMP_REG0.b0, SDFM_CFG_BASE_PTR_REG, SDFM_CFG_CH1_OSR_OFFSET, SDFM_CFG_OSR_SZ QBBC SDFM_SKIP0_CH2, TEMP_REG3.b0, 1 ;configure fast detect one count and enable fast detect LBBO &FAST_WINDOW_REG, SDFM_CFG_BASE_PTR_REG, SDFM_CFG_CH1_FD_WD_REG_OFFSET, 1 LBBO &FAST_ONE_MIN_REG, SDFM_CFG_BASE_PTR_REG, SDFM_CFG_CH1_FD_ONE_MIN_REG_OFFSET, 1 LBBO &FAST_ONE_MAX_REG, SDFM_CFG_BASE_PTR_REG, SDFM_CFG_CH1_FD_ONE_MAX_REG_OFFSET, 1 MOV TEMP_REG0.b1, FAST_WINDOW_REG LSL TEMP_REG0.b2, FAST_ONE_MIN_REG, 3 OR TEMP_REG0.b1, TEMP_REG0.b2, TEMP_REG0.b1 LSL TEMP_REG0.b2, FAST_ONE_MAX_REG, 1 OR TEMP_REG0.b2, TEMP_REG0.b2, 0x41;clear max & MIN threshold hit OR TEMP_REG0.b2, TEMP_REG0.b2, 0x80;enable fast detect JMP SDFM_SKIP0_CH2 SDFM_SKIP0_CH1: QBNE SDFM_SKIP0_CH2, TEMP_REG2.b0, SD_CH2_ID ; Load TR0.b0 <- SDFM_CFG_OSR load osr from DMEM for ch2 LBBO &TEMP_REG0.b0, SDFM_CFG_BASE_PTR_REG, SDFM_CFG_CH2_OSR_OFFSET, SDFM_CFG_OSR_SZ QBBC SDFM_SKIP0_CH2, TEMP_REG3.b0, 2 ;configure fast detect one count and enable fast detect LBBO &FAST_WINDOW_REG, SDFM_CFG_BASE_PTR_REG, SDFM_CFG_CH2_FD_WD_REG_OFFSET, 1 LBBO &FAST_ONE_MIN_REG, SDFM_CFG_BASE_PTR_REG, SDFM_CFG_CH2_FD_ONE_MIN_REG_OFFSET, 1 LBBO &FAST_ONE_MAX_REG, SDFM_CFG_BASE_PTR_REG, SDFM_CFG_CH2_FD_ONE_MAX_REG_OFFSET, 1 MOV TEMP_REG0.b1, FAST_WINDOW_REG LSL TEMP_REG0.b2, FAST_ONE_MIN_REG, 3 OR TEMP_REG0.b1, TEMP_REG0.b2, TEMP_REG0.b1 LSL TEMP_REG0.b2, FAST_ONE_MAX_REG, 1 ;clear max & min threshold hit OR TEMP_REG0.b2, TEMP_REG0.b2, 0x41 ;fast detect is enabled at a later stage OR TEMP_REG0.b2, TEMP_REG0.b2, 0x80 SDFM_SKIP0_CH2: LSL TEMP_REG2, TEMP_REG2, 3 ; (ChID*8) bytes to Byte0 PRUn_SD_SAMPLE_SIZE_REG(ChID) ADD TEMP_REG2, TEMP_REG2, 4 ; 4 bytes added for Byte0 PRUn_SD_SAMPLE_SIZE_REG0 SBBO &TEMP_REG0, SD_HW_BASE_PTR_REG, TEMP_REG2, 3 ; TR0.b0 -> PRUn_SD_SAMPLE_SIZE_REG(ChID) LSR TEMP_REG1, TEMP_REG1, 4 ; LS byte is ID for Ch(i+1) ; FL fix me config_osr_loop_end: JMP RET_ADDR_REG ; ; Configure SD channels. For SD channels, initialize: ; ACC select = ACC3 ; Clock inversion ; Clock source: pr1_pru_pru_r31_in[16] Primary Input ; FD: fast detect zero count ; SDFM_CFG_BASE_PTR_REG: base address of SD Configuration registers (&IEP_CFG_EPWM_PRD) ; SD_HW_BASE_PTR_REG: base address of SD HW configuration registers (&ICSSG_PRUn_SD_CLK_SEL_REG0) ; ; FN_CONFIG_SD_CLK_SEL_REG: ;load fast detect enable bit LBBO &TEMP_REG3, SDFM_CFG_BASE_PTR_REG, SDFM_CFG_SD_EN_FD_OFFSET, 1 LDI TEMP_REG0, 0 ; Load TR1.w0 <- SDFM_CFG_SD_CH_ID ;LDI TEMP_REG1.w0, 0x210 =001100010000 LBBO &TEMP_REG1.w0, SDFM_CFG_BASE_PTR_REG, SDFM_CFG_SD_CH_ID_OFFSET, SDFM_CFG_SD_CH_ID_SZ LOOP config_sd_ch_loop_end, ICSSG_NUM_SD_CH_FW ; loop over SD channels AND TEMP_REG2.b0, TEMP_REG1.b0, BF_SD_CH0_ID_MASK ; LS byte is ID for Chi QBNE SDFM_SKIP1_CH0, TEMP_REG2.b0, SD_CH0_ID ; Select clock inversion LDI TEMP_REG0.w0, 0; LBBO &TEMP_REG0.w2, SDFM_CFG_BASE_PTR_REG, SDFM_CFG_CH0_CLOCK_INVERSION_OFFSET, 1 LSL TEMP_REG0.b2, TEMP_REG0.b2, PRUn_SD_CLK_INVi_SHIFT AND TEMP_REG0.b0, TEMP_REG0.b2, PRUn_SD_CLK_INVi_MASK< PRUn_SD_CLK_SEL_REGi LSR TEMP_REG1, TEMP_REG1, 4 ; LS byte is ID for Ch(i+1) ; FL fix me config_sd_ch_loop_end: JMP RET_ADDR_REG ; ; Reset SD channel hardware ; ; SDFM_CFG_BASE_PTR_REG: base address of SD Configuration registers ; FN_RESET_SD_CH_HW: ; Load T01.w0 <- SDFM_CFG_SD_CH_ID ;LDI TEMP_REG0.w0, 0x210 LBBO &TEMP_REG0.w0, SDFM_CFG_BASE_PTR_REG, SDFM_CFG_SD_CH_ID_OFFSET, SDFM_CFG_SD_CH_ID_SZ LOOP reset_sd_ch_hw_loop_end, ICSSG_NUM_SD_CH_FW ; loop over SD channels AND TEMP_REG1.b0, TEMP_REG0.b0, BF_SD_CH0_ID_MASK ; LS byte is ID for Chi ; Set R30[29-26]:channel_select = channel ID. ; Set R30[25]:channel_en=1 (set Global Channel enable). LSL TEMP_REG1.b0, TEMP_REG1.b0, 2 ; TR1.b0 = TR1.b0<<2 = (Ch ID)<<2 SET TEMP_REG1.b0.t1 ; R30[25] channel_enable=1 MOV R30.b3, TEMP_REG1.b0 ; R30.b3 = TR1.b0 ; select SD Channel (Ch ID) LSR TEMP_REG0, TEMP_REG0, 4 ; LS byte is ID for Ch(i+1) ; FL fix me SET R31.t23 ; R31[23] re_init=1 reset_sd_ch_hw_loop_end: JMP RET_ADDR_REG ; ;PWM trip zone block configuration FN_CONFIG_PWM_REG: ;PWMx register offset LDI TEMP_REG1, ICSSG_CFG_PWMx LBCO &TEMP_REG0, CT_PRU_ICSSG_CFG, TEMP_REG1, 4 ;set trip mask for over current error LBBO &COMPARATOR_EN, SDFM_CFG_BASE_PTR_REG, SDFM_CFG_SD_EN_COMP_OFFSET, SDFM_CFG_EN_COMP_SZ QBBC SKIP_OVER_CURRENT_MASK, COMPARATOR_EN, SDFM_CFG_EN_COMP_BIT SET TEMP_REG0.b1, TEMP_REG0.b1, 1 SKIP_OVER_CURRENT_MASK: ;set trip mask for fast detect block error ;Load fast detect enable bits LBBO &TEMP_REG2.w0, SDFM_CFG_BASE_PTR_REG, SDFM_CFG_SD_CH_ID_OFFSET, SDFM_CFG_SD_CH_ID_SZ LBBO &TEMP_REG3, SDFM_CFG_BASE_PTR_REG, SDFM_CFG_SD_EN_FD_OFFSET, 1 QBBC END_MASK_CONFIG, TEMP_REG3, 0 AND TEMP_REG1.b0, TEMP_REG2.b0, 0xF QBNE SDFM_MASK_SKIP1_CH0, TEMP_REG1.b0, SD_CH0_ID OR TEMP_REG0.b1, TEMP_REG0.b1, 4 SDFM_MASK_SKIP1_CH0 LSR TEMP_REG2, TEMP_REG2, 4 AND TEMP_REG1.b0, TEMP_REG2.b0, 0xF QBNE SDFM_MASK_SKIP1_CH1, TEMP_REG1.b0, SD_CH1_ID OR TEMP_REG0.b1, TEMP_REG0.b1, 8 SDFM_MASK_SKIP1_CH1 LSR TEMP_REG2, TEMP_REG2, 4 AND TEMP_REG1.b0, TEMP_REG2.b0, 0xF QBNE SDFM_MASK_SKIP1_CH2, TEMP_REG1.b0, SD_CH2_ID OR TEMP_REG0.b1, TEMP_REG0.b1, 16 SDFM_MASK_SKIP1_CH2: END_MASK_CONFIG: LDI TEMP_REG1, ICSSG_CFG_PWMx SBCO &TEMP_REG0, CT_PRU_ICSSG_CFG, TEMP_REG1, 4 JMP RET_ADDR_REG ;Phase delay measurement ; Measure Phase Difference between MCLK and MDATA ; PRU mode is GPI mode (default) ; 1)Waits for rising edge of DATA using wbs instruction ; ->GPO1 for SD_D ; 2)check status of sd clock pin when data line is high. ; ->GPO16 for SD_clock ; 3)if clock line is high then call falling edge macro otherwise raising edge macro ; -> macro calcultes time between rising edge of data and upcoming nearest clock edge (rising or falling) ; -> store 8 times calculted time into DMEM SDFM_CLOCK_PHASE_COMPENSATION: ;decide mask LDI32 TEMP_REG1, SDFM_11_MASK ; waiting zero wbc R31.b0, 1 ;waiting for rising edge of sd data wbs R31.b0, 1 ; check nereset clock edge from starting point of bit AND TEMP_REG0, R31, TEMP_REG1 ;Max value LDI TEMP_REG2, 0 QBEQ DELAY_CAL_FOR_FALLING_EDGE, TEMP_REG0, TEMP_REG1 LDI TEMP_REG1, 0 LOOP SDFM_CLOCK_PHASE_COMPENSATION_LOOP, 8 M_SDFM_PHASE_DELAY_FOR_RAISING_EDGE SDFM_CLOCK_PHASE_COMPENSATION_LOOP: JMP END_PHASE_DELAY DELAY_CAL_FOR_FALLING_EDGE: LDI TEMP_REG1, 0 LOOP SDFM_CLOCK_PHASE_COMPENSATION_LOOP1, 8 M_SDFM_PHASE_DELAY_FOR_FALLING_EDGE SDFM_CLOCK_PHASE_COMPENSATION_LOOP1: END_PHASE_DELAY: ;storing phase delay (8 times) and edge status in DMEM ;final result in TEMP_REG1 register LSR TEMP_REG0, TEMP_REG1.w0, 3 SUB TEMP_REG0, TEMP_REG2,TEMP_REG0 QBLT SDFM_CLOCK_PHASE_COMPENSATION, TEMP_REG0, 1 SBBO &TEMP_REG1, SDFM_CFG_BASE_PTR_REG, SDFM_CFG_SD_CLOCK_PHASE_DELAY, 4 JMP RET_ADDR_REG ; ; Initialize SD (eCAP PWM) clock ; ; Arguments: ; SDFM_CFG_BASE_PTR_REG: base address of SD Configuration registers (&IEP_CFG_EPWM_PRD) ; FN_INIT_SD_CLOCK: ; Set eCAP PWM mode LDI32 TEMP_REG0, (SYNCI_EN_VAL<