This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TDA4VM: TDA4VM SPI1 RX abnormal

Part Number: TDA4VM

Hi Tiers,

       Recently, we encountered a problem that has been troubled for a long time. We use SPI0 to send data to the MCU regularly, and use SPI1 to receive the data sent by the MCU regularly. At this time, the sending cycle of the MCU is 10ms, and the data sent each time is 64 bytes. Under normal temperature and the CPU load is not high, all data received by SPI1 is normal. The abnormal conditions are as follows:

1) At an ambient temperature of 85°C, the core temperature reaches 120°C. After SPI1 receives and runs for 23382 seconds, it suddenly fails to respond to interrupts, receiving abnormalities, and getting stuck in the corresponding vxProcessGraph function. The CPU load rate at this time is as follows:

Summary of CPU load,
====================

CPU: mpu1_0: TOTAL LOAD =  29.57 % ( HWI =   5.33 %, SWI =  16.89 % )
CPU: mcu2_0: TOTAL LOAD =  33.81 % ( HWI =   5.47 %, SWI =   1.51 % )
CPU: mcu2_1: TOTAL LOAD =   9.14 % ( HWI =   1.32 %, SWI =   0.57 % )
CPU:  c6x_1: TOTAL LOAD =  89.77 % ( HWI =   0.86 %, SWI =   0.34 % )
CPU:  c6x_2: TOTAL LOAD =   9.82 % ( HWI =   0.12 %, SWI =   0. 5 % )
CPU:  c7x_1: TOTAL LOAD =   0. 9 % ( HWI =   0. 5 %, SWI =   0. 2 % )


HWA performance statistics,
===========================

HWA:   VISS: LOAD =  22. 5 % ( 564 MP/s )
HWA:   MSC0: LOAD =  28.42 % ( 696 MP/s )
HWA:   MSC1: LOAD =  28.56 % ( 693 MP/s )
HWA:  VENC0: LOAD =  43. 1 % ( 141 MP/s )


DDR performance statistics,
===========================

DDR: READ  BW: AVG =   1565 MB/s, PEAK =   2207 MB/s
DDR: WRITE BW: AVG =   1188 MB/s, PEAK =   1684 MB/s
DDR: TOTAL BW: AVG =   2753 MB/s, PEAK =   3891 MB/s


Detailed CPU performance/memory statistics,
===========================================

CPU: mcu2_0: TASK:           IPC_RX:   0.40 %
CPU: mcu2_0: TASK:       REMOTE_SRV:   0. 0 %
CPU: mcu2_0: TASK:         TIVX_CPU:   2.68 %
CPU: mcu2_0: TASK:          TIVX_NF:   0. 0 %
CPU: mcu2_0: TASK:        TIVX_LDC1:   0. 0 %
CPU: mcu2_0: TASK:        TIVX_MSC1:   3.62 %
CPU: mcu2_0: TASK:        TIVX_MSC2:   4.92 %
CPU: mcu2_0: TASK:       TIVX_VISS1:   5.46 %
CPU: mcu2_0: TASK:       TIVX_VISS2:   0. 0 %
CPU: mcu2_0: TASK:       TIVX_CAPT1:   1.19 %
CPU: mcu2_0: TASK:       TIVX_CAPT2:   1.12 %
CPU: mcu2_0: TASK:       TIVX_DISP1:   0. 0 %
CPU: mcu2_0: TASK:       TIVX_DISP2:   0. 0 %
CPU: mcu2_0: TASK:       TIVX_CSITX:   0. 9 %
CPU: mcu2_0: TASK:       TIVX_CAPT3:   0. 0 %
CPU: mcu2_0: TASK:       TIVX_CAPT4:   0. 0 %

CPU: mcu2_0: HEAP:   DDR_SHARED_MEM: size =    8388608 B, free =    7658496 B ( 91 % unused)
CPU: mcu2_0: HEAP:           L3_MEM: size =     131072 B, free =      98304 B ( 75 % unused)
CPU: mcu2_0: HEAP:  DDR_NON_CACHE_M: size =      65536 B, free =      65536 B (100 % unused)
CPU: mcu2_1: TASK:           IPC_RX:   0.62 %
CPU: mcu2_1: TASK:       REMOTE_SRV:   0. 0 %
CPU: mcu2_1: TASK:         TIVX_CPU:   0. 0 %
CPU: mcu2_1: TASK:         TIVX_SDE:   0. 0 %
CPU: mcu2_1: TASK:         TIVX_DOF:   0. 0 %
CPU: mcu2_1: TASK:       TIVX_VDEC1:   0. 0 %
CPU: mcu2_1: TASK:       TIVX_VDEC2:   0. 0 %
CPU: mcu2_1: TASK:       TIVX_VENC1:   1.97 %
CPU: mcu2_1: TASK:       TIVX_VENC2:   0. 0 %
CPU: mcu2_1: TASK:       TIVX_SPITX:   0.29 %
CPU: mcu2_1: TASK:       TIVX_SPIRX:   2.66 %
CPU: mcu2_1: TASK:      IPC_TEST_RX:   0. 0 %
CPU: mcu2_1: TASK:      IPC_TEST_TX:   0. 0 %
CPU: mcu2_1: TASK:      IPC_TEST_TX:   0. 0 %
CPU: mcu2_1: TASK:      IPC_TEST_TX:   0. 0 %
CPU: mcu2_1: TASK:      IPC_TEST_TX:   0. 0 %

CPU: mcu2_1: HEAP:   DDR_SHARED_MEM: size =   16777216 B, free =   13456640 B ( 80 % unused)
CPU: mcu2_1: HEAP:           L3_MEM: size =     131072 B, free =     131072 B (100 % unused)
CPU: mcu2_1: HEAP:  DDR_NON_CACHE_M: size =   67043328 B, free =    5967872 B (  8 % unused)

CPU:  c6x_1: TASK:           IPC_RX:   0. 4 %
CPU:  c6x_1: TASK:       REMOTE_SRV:   0. 0 %
CPU:  c6x_1: TASK:         TIVX_CPU:  88.49 %
CPU:  c6x_1: TASK:      IPC_TEST_RX:   0. 0 %
CPU:  c6x_1: TASK:      IPC_TEST_TX:   0. 0 %
CPU:  c6x_1: TASK:      IPC_TEST_TX:   0. 0 %
CPU:  c6x_1: TASK:      IPC_TEST_TX:   0. 0 %
CPU:  c6x_1: TASK:      IPC_TEST_TX:   0. 0 %
CPU:  c6x_1: TASK:      IPC_TEST_TX:   0. 0 %

CPU:  c6x_1: HEAP:   DDR_SHARED_MEM: size =   16777216 B, free =   16774912 B ( 99 % unused)
CPU:  c6x_1: HEAP:           L2_MEM: size =     229376 B, free =     229376 B (100 % unused)
CPU:  c6x_1: HEAP:  DDR_SCRATCH_MEM: size =   50331648 B, free =   50331648 B ( 14 % unused)

CPU:  c6x_2: TASK:           IPC_RX:   0. 0 %
CPU:  c6x_2: TASK:       REMOTE_SRV:   0. 0 %
CPU:  c6x_2: TASK:         TIVX_CPU:   9.63 %
CPU:  c6x_2: TASK:      IPC_TEST_RX:   0. 0 %
CPU:  c6x_2: TASK:      IPC_TEST_TX:   0. 0 %
CPU:  c6x_2: TASK:      IPC_TEST_TX:   0. 0 %
CPU:  c6x_2: TASK:      IPC_TEST_TX:   0. 0 %
CPU:  c6x_2: TASK:      IPC_TEST_TX:   0. 0 %
CPU:  c6x_2: TASK:      IPC_TEST_TX:   0. 0 %

CPU:  c6x_2: HEAP:   DDR_SHARED_MEM: size =   16777216 B, free =   16774912 B ( 99 % unused)
CPU:  c6x_2: HEAP:           L2_MEM: size =     229376 B, free =     229376 B (100 % unused)
CPU:  c6x_2: HEAP:  DDR_SCRATCH_MEM: size =   50331648 B, free =   50331648 B ( 14 % unused)
CPU:  c7x_1: TASK:           IPC_RX:   0. 0 %
CPU:  c7x_1: TASK:       REMOTE_SRV:   0. 0 %
CPU:  c7x_1: TASK:         TIVX_CPU:   0. 0 %
CPU:  c7x_1: TASK:      IPC_TEST_RX:   0. 0 %
CPU:  c7x_1: TASK:      IPC_TEST_TX:   0. 0 %
CPU:  c7x_1: TASK:      IPC_TEST_TX:   0. 0 %
CPU:  c7x_1: TASK:      IPC_TEST_TX:   0. 0 %
CPU:  c7x_1: TASK:      IPC_TEST_TX:   0. 0 %
CPU:  c7x_1: TASK:      IPC_TEST_TX:   0. 0 %

CPU:  c7x_1: HEAP:   DDR_SHARED_MEM: size =  268435456 B, free =  268435456 B (  4 % unused)
CPU:  c7x_1: HEAP:           L3_MEM: size =    8159232 B, free =    8159232 B (100 % unused)
CPU:  c7x_1: HEAP:           L2_MEM: size =     491520 B, free =     491520 B (100 % unused)
CPU:  c7x_1: HEAP:           L1_MEM: size =      16384 B, free =      16384 B (100 % unused)
CPU:  c7x_1: HEAP:  DDR_SCRATCH_MEM: size =  234881024 B, free =  234881024 B (  8 % unused)

Corresponding log spi_rx_test.zip2289181 line 

2) Under normal temperature, increase the CPU load rate. After SPI1 receives and runs normally for 3540 seconds, it suddenly fails to respond to interrupts, receiving abnormalities, and getting stuck in the corresponding vxProcessGraph function. The CPU load rate at this time is as follows:

Summary of CPU load,                                                                             
====================                                                                             
                                                                                                 
CPU: mpu1_0: TOTAL LOAD =  93.57 % ( HWI =   5.21 %, SWI =  19. 4 % )                            
CPU: mcu2_0: TOTAL LOAD =  32.42 % ( HWI =   8.34 %, SWI =   3. 3 % )                            
CPU: mcu2_1: TOTAL LOAD =   1. 4 % ( HWI =   0.18 %, SWI =   0.16 % )                            
CPU:  c6x_1: TOTAL LOAD =  91. 8 % ( HWI =   0.33 %, SWI =   0.41 % )                            
CPU:  c6x_2: TOTAL LOAD =  29.16 % ( HWI =   0.50 %, SWI =   0.22 % )                            
CPU:  c7x_1: TOTAL LOAD =  34.38 % ( HWI =   0. 7 %, SWI =   0. 6 % )                            
                                                                                                 
                                                                                                 
HWA performance statistics,                                                                      
===========================                                                                      
                                                                                                 
HWA:   MSC0: LOAD =   3.87 % ( 390 MP/s )                                                        
HWA:   MSC1: LOAD =   3.78 % ( 300 MP/s )                                                        
                                                                                                 
                                                                                                 
DDR performance statistics,                                                                      
===========================                                                                      
                                                                                                 
DDR: READ  BW: AVG =   3519 MB/s, PEAK =   4707 MB/s                                             
DDR: WRITE BW: AVG =   3611 MB/s, PEAK =   4831 MB/s                                             
DDR: TOTAL BW: AVG =   7130 MB/s, PEAK =   9538 MB/s                                             
                                                                                                 
                                                                                                 
Detailed CPU performance/memory statistics,                                                      
===========================================                                                      
                                                                                                 
CPU: mcu2_0: TASK:           IPC_RX:   0.47 %                                                    
CPU: mcu2_0: TASK:       REMOTE_SRV:   0. 7 %                                                    
CPU: mcu2_0: TASK:         TIVX_CPU:   0. 0 %                                                    
CPU: mcu2_0: TASK:          TIVX_NF:   0. 0 %                                                    
CPU: mcu2_0: TASK:        TIVX_LDC1:   0. 0 %                                                    
CPU: mcu2_0: TASK:        TIVX_MSC1:   2.28 %                                                    
CPU: mcu2_0: TASK:        TIVX_MSC2:   2. 6 %                                                    
CPU: mcu2_0: TASK:       TIVX_VISS1:   0. 0 %                                                    
CPU: mcu2_0: TASK:       TIVX_VISS2:   0. 0 %                                                    
CPU: mcu2_0: TASK:       TIVX_CAPT1:   0. 0 %                                                    
CPU: mcu2_0: TASK:       TIVX_CAPT2:   3.66 %                                                    
CPU: mcu2_0: TASK:       TIVX_DISP1:   0.95 %                                                    
CPU: mcu2_0: TASK:       TIVX_DISP2:   0. 0 %                                                    
CPU: mcu2_0: TASK:       TIVX_CSITX:   0.17 %  
CPU: mcu2_0: TASK:       TIVX_CAPT3:   0. 0 %                                                    
CPU: mcu2_0: TASK:       TIVX_CAPT4:   0. 0 %                                                    
                                                                                                 
CPU: mcu2_0: HEAP:   DDR_SHARED_MEM: size =    8388608 B, free =    8251136 B ( 98 % unused)     
CPU: mcu2_0: HEAP:           L3_MEM: size =     131072 B, free =     131072 B (100 % unused)     
CPU: mcu2_0: HEAP:  DDR_NON_CACHE_M: size =      65536 B, free =      65536 B (100 % unused)     
                                                                                                 
CPU: mcu2_1: TASK:           IPC_RX:   0.11 %                                                    
CPU: mcu2_1: TASK:       REMOTE_SRV:   0. 3 %                                                    
CPU: mcu2_1: TASK:         TIVX_CPU:   0. 0 %                                                    
CPU: mcu2_1: TASK:         TIVX_SDE:   0. 0 %                                                    
CPU: mcu2_1: TASK:         TIVX_DOF:   0. 0 %                                                    
CPU: mcu2_1: TASK:       TIVX_VDEC1:   0. 0 %                                                    
CPU: mcu2_1: TASK:       TIVX_VDEC2:   0. 0 %                                                    
CPU: mcu2_1: TASK:       TIVX_VENC1:   0. 0 %                                                    
CPU: mcu2_1: TASK:       TIVX_VENC2:   0. 0 %                                                    
CPU: mcu2_1: TASK:       TIVX_SPITX:   0.50 %                                                    
CPU: mcu2_1: TASK:       TIVX_SPIRX:   0. 0 %                                                    
CPU: mcu2_1: TASK:      IPC_TEST_RX:   0. 0 %                                                    
CPU: mcu2_1: TASK:      IPC_TEST_TX:   0. 0 %                                                    
CPU: mcu2_1: TASK:      IPC_TEST_TX:   0. 0 %                                                    
CPU: mcu2_1: TASK:      IPC_TEST_TX:   0. 0 %                                                    
CPU: mcu2_1: TASK:      IPC_TEST_TX:   0. 0 %                                                    
                                                                                                 
CPU: mcu2_1: HEAP:   DDR_SHARED_MEM: size =   16777216 B, free =   13456640 B ( 80 % unused)     
CPU: mcu2_1: HEAP:           L3_MEM: size =     131072 B, free =     131072 B (100 % unused)     
CPU: mcu2_1: HEAP:  DDR_NON_CACHE_M: size =   67043328 B, free =   25694208 B ( 38 % unused)     
                                                                                                 
CPU:  c6x_1: TASK:           IPC_RX:   0. 7 %                                                    
CPU:  c6x_1: TASK:       REMOTE_SRV:   0. 1 %                                                    
CPU:  c6x_1: TASK:         TIVX_CPU:  90.21 %                                                    
CPU:  c6x_1: TASK:      IPC_TEST_RX:   0. 0 %                                                    
CPU:  c6x_1: TASK:      IPC_TEST_TX:   0. 0 %                                                    
CPU:  c6x_1: TASK:      IPC_TEST_TX:   0. 0 %                                                    
CPU:  c6x_1: TASK:      IPC_TEST_TX:   0. 0 %                                                    
CPU:  c6x_1: TASK:      IPC_TEST_TX:   0. 0 %                                                    
CPU:  c6x_1: TASK:      IPC_TEST_TX:   0. 0 %                                                    
                                                                                                 
CPU:  c6x_1: HEAP:   DDR_SHARED_MEM: size =   16777216 B, free =   16760064 B ( 99 % unused)     
CPU:  c6x_1: HEAP:           L2_MEM: size =     229376 B, free =          0 B (  0 % unused)     
CPU:  c6x_1: HEAP:  DDR_SCRATCH_MEM: size =   50331648 B, free =   50331648 B ( 14 % unused)     
CPU:  c6x_2: TASK:           IPC_RX:   0. 3 %                                                    
CPU:  c6x_2: TASK:       REMOTE_SRV:   0. 0 %                                                    
CPU:  c6x_2: TASK:         TIVX_CPU:  28.36 %                                                    
CPU:  c6x_2: TASK:      IPC_TEST_RX:   0. 0 %                                                    
CPU:  c6x_2: TASK:      IPC_TEST_TX:   0. 0 %                                                    
CPU:  c6x_2: TASK:      IPC_TEST_TX:   0. 0 %                                                    
CPU:  c6x_2: TASK:      IPC_TEST_TX:   0. 0 %                                                    
CPU:  c6x_2: TASK:      IPC_TEST_TX:   0. 0 %                                                    
CPU:  c6x_2: TASK:      IPC_TEST_TX:   0. 0 %                                                    
                                                                                                 
CPU:  c6x_2: HEAP:   DDR_SHARED_MEM: size =   16777216 B, free =   16750336 B ( 99 % unused)     
CPU:  c6x_2: HEAP:           L2_MEM: size =     229376 B, free =     229376 B (100 % unused)     
CPU:  c6x_2: HEAP:  DDR_SCRATCH_MEM: size =   50331648 B, free =   50331648 B ( 14 % unused)     
                                                                                                 
CPU:  c7x_1: TASK:           IPC_RX:   0. 3 %                                                    
CPU:  c7x_1: TASK:       REMOTE_SRV:   0. 0 %                                                    
CPU:  c7x_1: TASK:         TIVX_CPU:  34.20 %                                                    
CPU:  c7x_1: TASK:      IPC_TEST_RX:   0. 0 %                                                    
CPU:  c7x_1: TASK:      IPC_TEST_TX:   0. 0 %                                                    
CPU:  c7x_1: TASK:      IPC_TEST_TX:   0. 0 %                                                    
CPU:  c7x_1: TASK:      IPC_TEST_TX:   0. 0 %                                                    
CPU:  c7x_1: TASK:      IPC_TEST_TX:   0. 0 %                                                    
CPU:  c7x_1: TASK:      IPC_TEST_TX:   0. 0 %                                                    
                                                                                                 
CPU:  c7x_1: HEAP:   DDR_SHARED_MEM: size =  268435456 B, free =  247093248 B ( 12 % unused)     
CPU:  c7x_1: HEAP:           L3_MEM: size =    8159232 B, free =          0 B (  0 % unused)     
CPU:  c7x_1: HEAP:           L2_MEM: size =     491520 B, free =     491520 B (100 % unused)     
CPU:  c7x_1: HEAP:           L1_MEM: size =      16384 B, free =          0 B (  0 % unused)     
CPU:  c7x_1: HEAP:  DDR_SCRATCH_MEM: size =  234881024 B, free =  214909692 B (  0 % unused)

Corresponding log spi_rx_test.zip line 39285 

The driver of SPI1 is ~/ti-processor-sdk-rtos-j721e-evm-07_01_00_11/pdk_jacinto_07_01_00_45/packages/ti/drv/spi/src/v1/SPI_v1.c

The vx_spirx_target.c corresponding to SPI1 is as follows:

/*
 *
 * Copyright (c) 2018 Texas Instruments Incorporated
 *
 * All rights reserved not granted herein.
 *
 * Limited License.
 *
 * Texas Instruments Incorporated grants a world-wide, royalty-free, non-exclusive
 * license under copyrights and patents it now or hereafter owns or controls to make,
 * have made, use, import, offer to sell and sell ("Utilize") this software subject to the
 * terms herein.  With respect to the foregoing patent license, such license is granted
 * solely to the extent that any such patent is necessary to Utilize the software alone.
 * The patent license shall not apply to any combinations which include this software,
 * other than combinations with devices manufactured by or for TI ("TI Devices").
 * No hardware patent is licensed hereunder.
 *
 * Redistributions must preserve existing copyright notices and reproduce this license
 * (including the above copyright notice and the disclaimer and (if applicable) source
 * code license limitations below) in the documentation and/or other materials provided
 * with the distribution
 *
 * Redistribution and use in binary form, without modification, are permitted provided
 * that the following conditions are met:
 *
 * *       No reverse engineering, decompilation, or disassembly of this software is
 * permitted with respect to any software provided in binary form.
 *
 * *       any redistribution and use are licensed by TI for use only with TI Devices.
 *
 * *       Nothing shall obligate TI to provide you with source code for the software
 * licensed and provided to you in object code.
 *
 * If software source code is provided to you, modification and redistribution of the
 * source code are permitted provided that the following conditions are met:
 *
 * *       any redistribution and use of the source code, including any resulting derivative
 * works, are licensed by TI for use only with TI Devices.
 *
 * *       any redistribution and use of any object code compiled from the source code
 * and any resulting derivative works, are licensed by TI for use only with TI Devices.
 *
 * Neither the name of Texas Instruments Incorporated nor the names of its suppliers
 *
 * may be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * DISCLAIMER.
 *
 * THIS SOFTWARE IS PROVIDED BY TI AND TI'S LICENSORS "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 TI AND TI'S LICENSORS 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.
 *
 */
/* ========================================================================== */
/*                             Include Files                                  */
/* ========================================================================== */
#include <stdio.h>
// // #include <ti/csl/csl_mcspi.h>
// #include <ti/csl/soc.h>
// #include <ti/drv/uart/UART_stdio.h>
#include <ti/drv/spi/SPI.h>
#include <ti/board/board.h>
#include <ti/csl/src/ip/mcspi/V0/mcspi.h>
#include <ti/osal/RegisterIntr.h>
#include <ti/drv/spi/src/SPI_osal.h>
#include "TI/tivx_yh_pdd.h"

#include <TI/tivx_task.h>
#include "TI/tivx.h"
#include "TI/j7.h"
#include "TI/tivx_yh_pdd_spi.h"
#include <TI/tivx_yh_pdd.h>
#include "TI/tivx_event.h"
#include <ti/sysbios/knl/Event.h>
#include <ti/sysbios/BIOS.h>

#include "TI/tivx_target_kernel.h"
#include "tivx_kernel_spirx.h"

#include <ti/csl/soc/j721e/src/cslr_intr_r5fss0_core0.h>
#include <ti/csl/soc/j721e/src/cslr_intr_r5fss0_core1.h>
#include <ti/csl/soc/j721e/src/cslr_intr_r5fss1_core0.h>
#include <ti/csl/soc/j721e/src/cslr_intr_r5fss1_core1.h>
#include <ti/csl/soc/j721e/src/cslr_intr_r5fss0_introuter0.h>


#include <ti/drv/spi/SPI.h>
#include <ti/drv/spi/soc/SPI_v1.h>

#include <ti/drv/spi/soc/SPI_soc.h>
#include <ti/drv/spi/src/SPI_osal.h>
#include <ti/drv/spi/SPI.h>
#include <ti/drv/spi/MCSPI.h>

Event_Handle        gSpirxIntrEvent;
Event_Struct        gSpirxIntrEventMem;



/* ========================================================================== */
/*                                 Macros                                     */
/* ========================================================================== */
#define MCSPIRX_IN_CLK                (48000000U)
#define MCSPIRX_OUT_CLK               (10000000U)
#define McSPIRX_DATA_COUNT            (128)//(256U)
#define CSL_MCSPI0_CFG_BASE (0x2100000UL)
#define CSL_MCSPI1_CFG_BASE (0x2110000UL)
#define CSL_MCSPI2_CFG_BASE (0x2120000UL)
#define BUFFER_RECV_COUNT 10

/** \brief MCSPI Channel number*/
#define MCSPI_CH_NUM                (0U)
/* ========================================================================== */
/*                           when use interrupt used                         */
/* ========================================================================== */

/* ========================================================================== */
/*       when use spi2 used,tda4A for master, tda4B for slave                 */
/* ========================================================================== */

#define gMcSpi_tda4AMaster_to_tda4BSlave

/* ========================================================================== */
/*                    use when using spirx node alone                        */
/* ========================================================================== */

/* ========================================================================== */
/*                            Global Variables                                */
/* ========================================================================== */
uint32_t          gChNum_rx  = 0U;
uint8_t           gRxBuffer[McSPIRX_DATA_COUNT];
// static uint32_t mcspi_address_rx = 0;
uint32_t spi_initDoneFlag_rx = 0;
// static uint32_t is_tda4a = 0;//1-a芯片,0-b芯片
/* ========================================================================== */
/**/
/* ========================================================================== */


typedef struct tivxSpirxParams_t tivxSpirxParams;

struct tivxSpirxParams_t{
    SPI_TransferMode    transferMode;       /*!< Blocking or Callback mode */
    uint32_t            transferTimeout;    /*!< Transfer timeout in system
                                                 ticks (Not supported with all
                                                 implementations */
    SPI_CallbackFxn     transferCallbackFxn;/*!< Callback function pointer */
    SPI_Mode            mode;               /*!< Master or Slave mode */
    uint32_t            bitRate;            /*!< SPI bit rate in Hz */
    uint32_t            mcspirxIdx;
    uint32_t            dataSize;           /*!< SPI data frame size in bits */
    SPI_FrameFormat     frameFormat;        /*!< SPI frame format */
    void               *custom;             /*!< Custom argument used by driver
                                                 implementation */
};


static tivx_target_kernel vx_spirx_target_kernel = NULL;


static vx_status VX_CALLBACK tivxspiRxProcess(
       tivx_target_kernel_instance kernel,
       tivx_obj_desc_t *obj_desc[],
       uint16_t num_params, void *priv_arg);
static vx_status VX_CALLBACK tivxspiRxCreate(
       tivx_target_kernel_instance kernel,
       tivx_obj_desc_t *obj_desc[],
       uint16_t num_params, void *priv_arg);
static vx_status VX_CALLBACK tivxspirxDelete(
       tivx_target_kernel_instance kernel,
       tivx_obj_desc_t *obj_desc[],
       uint16_t num_params, void *priv_arg);
static vx_status VX_CALLBACK tivxspirxControl(
       tivx_target_kernel_instance kernel,
       uint32_t node_cmd_id, tivx_obj_desc_t *obj_desc[],
       uint16_t num_params, void *priv_arg);



extern void Board_delay(uint32_t delayCycles);

// static void McSPIMSPolledModeTransfer(uint16_t length)
// {
//     uint32_t          channelStatus = 0;
//     volatile uint32_t timeout1      = 0xFFFFU;
//     uint8_t          *p_rx;
//     // uint32_t count;

//     p_rx    = gRxBuffer;


//     // do{
//         while (0 != length)
//         {
//             timeout1      = 0xFFFF;
//             channelStatus = McSPIChannelStatusGet(mcspi_address_rx, gChNum_rx);
//             while (0 == (channelStatus & CSL_MCSPI_CH0STAT_RXS_MASK))
//             {
//                 channelStatus = 0;
//                 channelStatus = McSPIChannelStatusGet(mcspi_address_rx, gChNum_rx);

//                 --timeout1;
//                 if (0 == timeout1)
//                 {
//                     // printf("\nMCU McSPI2 RX Timed out!!");
//                     Board_delay(20);
//                     break;
//                 }
//             }
//                 *p_rx++ = (uint8_t)McSPIReceiveData(mcspi_address_rx, gChNum_rx);
//                 length--;
//         }

//         length = McSPIRX_DATA_COUNT;

//         // for(count =0; count < 3; count ++){
//         //     if(mcspi_address_rx == 0x2120000){
//         //         printf("MCSPI2 SLAVE MODE RECV BUFFER address= 0x%x, recv value = %d\n", mcspi_address_rx, gRxBuffer[count]);
//         //     }
//         //     // VX_PRINT(VX_ZONE_ERROR, "rx_node======= recv %d = %d\n", count,(uint32_t)(gRxBuffer[count]));
//         //     // gRxBuffer[count] = 0;
//         // }
//         Board_delay(2);
//     // }while(channelStatus != 1000);
// }


// static void slave_SPI1SetUp(void)
// {
//     /* Reset the McSPI instance.*/
//     McSPIReset(mcspi_address_rx);

//     /* AUTOIDLE      bit - Disable (OCP clock is running free, no gating)  */
//     MCSPISysConfigSetup(mcspi_address_rx, MCSPI_CLOCKS_OCP_ON_FUNC_ON,
//                         MCSPI_SIDLEMODE_NO, MCSPI_WAKEUP_DISABLE,
//                         MCSPI_AUTOIDLE_OFF);

//     /* Enable chip select pin.*/
//     McSPICSEnable(mcspi_address_rx);

//     /* Enable slave mode of operation.*/
//     McSPISlaveModeEnable(mcspi_address_rx);


// #ifdef gMcSpi_tda4AMaster_to_tda4BSlave
//     /* Configure the Pin Direction.*/
//     MCSPIPinDirSet(mcspi_address_rx, MCSPI_RX_ONLY_MODE,
//                             MCSPI_DATA_LINE_COMM_MODE_1, gChNum_rx);
// #else
//     /* Configure the Pin Direction.*/
//     MCSPIPinDirSet(mcspi_address_rx, MCSPI_RX_ONLY_MODE,
//                                 MCSPI_DATA_LINE_COMM_MODE_6, gChNum_rx);
// #endif

//     McSPIClkConfig(mcspi_address_rx, MCSPIRX_IN_CLK, MCSPIRX_OUT_CLK, gChNum_rx,
//                    MCSPI_CLK_MODE_1);

//     /* Configure the word length.*/
//     McSPIWordLengthSet(mcspi_address_rx, MCSPI_WORD_LENGTH(8), gChNum_rx);

//     /* Set polarity of SPIEN to low.*/
//     McSPICSPolarityConfig(mcspi_address_rx,
//                           (MCSPI_CH0CONF_EPOL_ACTIVELOW <<
//                            MCSPI_CH0CONF_EPOL_SHIFT), gChNum_rx);


//     McSPIRxFIFOConfig(mcspi_address_rx, MCSPI_RX_FIFO_ENABLE, gChNum_rx);
//     McSPITxFIFOConfig(mcspi_address_rx, MCSPI_TX_FIFO_DISABLE, gChNum_rx);


//     McSPIFIFOTrigLvlSet(mcspi_address_rx, 128, 1, MCSPI_RX_ONLY_MODE);

//     McSPIChannelEnable(mcspi_address_rx, gChNum_rx);
// }


extern void Board_delay(uint32_t delayCycles);

/* Test channel # */
#define MCSPI_TEST_CHN 0

#define SPI_TEST_ID_INT 1

static MCSPI_Handle spi;
static uint32_t xferLen = 64; /*length of information*/

typedef struct spi_Config_s{
    bool     (*testFunc)(void *);
    int32_t  testId;
    bool     master;
    bool     pollMode;
    bool     cbMode;
    bool     dmaMode;
    uint32_t timeout;
    char     testDesc[80];
    uint32_t param;
    uint32_t trigLvl;

}SPI_ConfigEx;

SPI_ConfigEx SPI_Configs = {
    NULL,
    SPI_TEST_ID_INT,
    false,
    false,
    false,
    false,
    0,
    NULL,
    1,
    64
};

/* Default MCSPI parameters structure */
const MCSPI_Params app_MCSPI1_defaultParams = {
    SPI_MODE_CALLBACK,  /* transferMode */
    0U,                 /* transferTimeout */
    NULL,               /* transferCallbackFxn */
    SPI_SLAVE,         /* mode */
    10000000,            /* bitRate */
    8,                  /* dataSize */
    SPI_POL0_PHA1,      /* frameFormat */
    NULL                /* custom */
};

const MCSPI_Params app_MCSPI2_defaultParams = {
    SPI_MODE_BLOCKING,  /* transferMode */
    0U,                 /* transferTimeout */
    NULL,               /* transferCallbackFxn */
    SPI_SLAVE,         /* mode */
    10000000,            /* bitRate */
    8,                  /* dataSize */
    SPI_POL0_PHA1,      /* frameFormat */
    NULL                /* custom */
};

static void MCSPI_InitConfig(uint32_t instance, int32_t Id, uint32_t chn, bool multiChn)
{
    SPI_HWAttrs spi_cfg;
    // int32_t     testId = Id;

    /* Get the default SPI init configurations */
    SPI_socGetInitCfg(instance, &spi_cfg);

    printf("instance = %d\n", instance);
    printf("spi_cfg.baseAddr = 0x%x\n", spi_cfg.baseAddr);
    printf("spi_cfg.intNum = %d\n", spi_cfg.intNum);
    /*
     * Set blocking mode (dma mode or non-dma interrupt mode)
     * or callback mode
     */

    /* interrupt enabled */
    spi_cfg.enableIntr = true;
    spi_cfg.edmaHandle = NULL;
    spi_cfg.dmaMode    = FALSE;

    /* Set the SPI init configurations */
    SPI_socSetInitCfg(instance, &spi_cfg);
}

static void MCSPI_Params_Init(MCSPI_Params *params, uint32_t instance)
{
    if ((params != NULL) && (instance == 1)){
        *params = app_MCSPI1_defaultParams;
    }else if((params != NULL) && (instance == 2)){
        *params = app_MCSPI2_defaultParams;
    }
}

/* Transaction data */
SPI_Transaction   transaction;
unsigned char masterRxBuffer[128] __attribute__ ((aligned (128)));
static uint32_t instance = 1;

#define CANCEL_TX_LEN   (1024)
unsigned char masterTxBuffer[128] = "PASS: Txd from master SPI PASS: Txd from master SPI PASS: Txd from master SPI ";
uint8_t slave1TxBuffer[128];
// uint8_t slave1RxBuffer[128];
uint8_t slave2TxBuffer[128];
uint8_t slave2RxBuffer[128];
uint8_t checkRxBuffer[128];


uint8_t array_ptr[BUFFER_RECV_COUNT][128];
#define DEBUG_YU

static bool SPI_mst_slv_xfer(void *spi, SPI_ConfigEx *test, uint32_t xferLen, uint32_t instance, uint8_t *rxBuffer)
{
    uintptr_t        addrMasterRxBuf, addrMasterTxBuf;// addrSlaveRxBuf, addrSlaveTxBuf;// addrCancelTxBuff, addrCancelRxBuff;
    bool            ret = false;
    uint32_t        terminateXfer = 1;
    bool            master = test->master;

    addrMasterRxBuf = (uintptr_t)masterRxBuffer;
    addrMasterTxBuf = (uintptr_t)masterTxBuffer;

    memset(slave1TxBuffer, 0, sizeof(slave1TxBuffer));
    // memset(slave1RxBuffer, 0, sizeof(slave1RxBuffer));
    memset(rxBuffer, 0, xferLen);
    memset(slave2TxBuffer, 0, sizeof(slave2TxBuffer));
    memset(slave2RxBuffer, 0, sizeof(slave2RxBuffer));
    /* Initialize slave SPI transaction structure */
    transaction.count = xferLen;
    transaction.arg = (void *)&terminateXfer;
    if (master == true)
    {
        transaction.txBuf = (void *)addrMasterTxBuf;
        transaction.rxBuf = (void *)addrMasterRxBuf;
    }
    else
    {
        if(instance == 1){
            // transaction.txBuf = (void *)slave1TxBuffer;
            // transaction.rxBuf = (void *)slave1RxBuffer;
            transaction.rxBuf = (void *)rxBuffer;
        }else if(instance == 2){
            transaction.txBuf = (void *)slave2TxBuffer;
            transaction.rxBuf = (void *)slave2RxBuffer;
        }
    }

    MCSPI_transfer((MCSPI_Handle)spi, &transaction);    



    ret = true;
    return ret;
}


#define SPIRX_TARGET_RX_DATA_EVENT     (Event_Id_00)

void MCSPI_transferCallback(MCSPI_Handle mcHandle, SPI_Transaction *transaction){
    Event_post(gSpirxIntrEvent, SPIRX_TARGET_RX_DATA_EVENT);
}

static void mcSpiInit(uint32_t instance, MCSPI_Params *spiParams){
    
    // uint32_t instance = 1; /*instance number represent MCSPI0,MCSPI1,MCSPI2*/

    MCSPI_InitConfig(instance, SPI_Configs.testId, MCSPI_TEST_CHN, false);
    MCSPI_Params_Init(spiParams, instance);

    spiParams->transferCallbackFxn = MCSPI_transferCallback;

    uint32_t timeout = SPI_Configs.timeout;
    spiParams->transferTimeout = timeout;

    spi = MCSPI_open(instance, MCSPI_TEST_CHN, spiParams);
    if (spi == NULL)
    {
        VX_PRINT(VX_ZONE_ERROR,"Error initializing SPI\n");
    }
    else
    {
        VX_PRINT(VX_ZONE_ERROR,"SPI initialized\n");
    }
}



static vx_status VX_CALLBACK tivxspiRxCreate(
       tivx_target_kernel_instance kernel,
       tivx_obj_desc_t *obj_desc[],
       uint16_t num_params, void *priv_arg)
{
    vx_status status = (vx_status)VX_SUCCESS;
    tivx_obj_desc_user_data_object_t *input_cfg_obj_desc;
    tivxSpirxParams *prms = NULL;
    void *spirx_config_target_ptr;
    tivx_spirx_params_t *params; 
    uint32_t index;

    for(index = 0; index < 128; index++){
        checkRxBuffer[index] = index;
    }
    
    if ( (num_params != TIVX_KERNEL_SPIRX_MAX_PARAMS)
        || (NULL == obj_desc[TIVX_KERNEL_SPIRX_INPUT_CFG_IDX])
        || (NULL == obj_desc[TIVX_KERNEL_SPIRX_OUTPUT_DATA_IDX])
    )
    {
        status = (vx_status)VX_FAILURE;
    }
    else
    {
        input_cfg_obj_desc = (tivx_obj_desc_user_data_object_t *)obj_desc[TIVX_KERNEL_SPIRX_INPUT_CFG_IDX];

        prms = tivxMemAlloc(sizeof(tivxSpirxParams), (vx_enum)TIVX_MEM_EXTERNAL);
        if (NULL != prms){
            memset(prms, 0, sizeof(tivxSpirxParams));
        }
        spirx_config_target_ptr = tivxMemShared2TargetPtr(&input_cfg_obj_desc->mem_ptr);

        tivxMemBufferMap(spirx_config_target_ptr, input_cfg_obj_desc->mem_size,
                            (vx_enum)VX_MEMORY_TYPE_HOST, (vx_enum)VX_READ_ONLY);

        params = (tivx_spirx_params_t *)spirx_config_target_ptr;
        printf("creat spi params = %d\n", params->mspiIdx);

        Event_Params eventParams;

        Event_Params_init(&eventParams);
        Event_construct(&gSpirxIntrEventMem, &eventParams);
        gSpirxIntrEvent =  Event_handle(&gSpirxIntrEventMem);

        MCSPI_Params spi1Params;
        mcSpiInit(instance, &spi1Params);

        tivxMemBufferUnmap(spirx_config_target_ptr,
                            input_cfg_obj_desc->mem_size, (vx_enum)VX_MEMORY_TYPE_HOST,
                            (vx_enum)VX_READ_ONLY);
    }
    return status;
}

uint8_t pdk_data[1];

static vx_status VX_CALLBACK tivxspiRxProcess(
       tivx_target_kernel_instance kernel,
       tivx_obj_desc_t *obj_desc[],
       uint16_t num_params, void *priv_arg)
{
    vx_status status = (vx_status)VX_SUCCESS;
    // tivxSpirxParams *prms = NULL;
    // vx_uint32 size;
    tivx_spirx_recvSlamCarInfo_t *mspiRecvData; 
    tivx_obj_desc_user_data_object_t *src_desc0;
    UInt postedEvents;
    
    if ( (num_params != TIVX_KERNEL_SPIRX_MAX_PARAMS)
        || (NULL == obj_desc[TIVX_KERNEL_SPIRX_INPUT_CFG_IDX])
        || (NULL == obj_desc[TIVX_KERNEL_SPIRX_OUTPUT_DATA_IDX])
    )
    {
        status = (vx_status)VX_FAILURE;
    }

    memset(pdk_data, 0, 1);

    if((vx_status)VX_SUCCESS == status)
    {
        void *src_desc0_target_ptr;

        src_desc0 = (tivx_obj_desc_user_data_object_t *)obj_desc[TIVX_KERNEL_SPIRX_OUTPUT_DATA_IDX];
        src_desc0_target_ptr = tivxMemShared2TargetPtr(&src_desc0->mem_ptr);

        /* Map all buffers, which invalidates the cache */
        tivxMemBufferMap(src_desc0_target_ptr,
            src_desc0->mem_size, VX_MEMORY_TYPE_HOST,
            VX_READ_ONLY);
        mspiRecvData = (tivx_spirx_recvSlamCarInfo_t *)src_desc0_target_ptr;
        
        if (SPI_mst_slv_xfer((void *)spi, &SPI_Configs, xferLen, instance, mspiRecvData->checkBuffer) == false){
            VX_PRINT(VX_ZONE_ERROR,"Error transfer SPI\n");
            printf("mspiRecvData = %d\n", mspiRecvData->pdvSpiStatus);
        }

        postedEvents = Event_pend(gSpirxIntrEvent,0,
                            SPIRX_TARGET_RX_DATA_EVENT,
                            BIOS_WAIT_FOREVER);

        if(postedEvents & SPIRX_TARGET_RX_DATA_EVENT){
      
        }
        // tivxTaskWaitMsecs(1);

        tivxMemBufferUnmap(src_desc0_target_ptr, src_desc0->mem_size, VX_MEMORY_TYPE_HOST, VX_WRITE_ONLY);
    }




    return status;
}




static vx_status VX_CALLBACK tivxspirxDelete(
       tivx_target_kernel_instance kernel,
       tivx_obj_desc_t *obj_desc[],
       uint16_t num_params, void *priv_arg)
{
    vx_status status = (vx_status)VX_SUCCESS;

    return status;
}


void tivxAddTargetKernelSpirx(void)
{
    char target_name[TIVX_TARGET_MAX_NAME];
    vx_enum self_cpu;

    self_cpu = tivxGetSelfCpuId();

    // if((self_cpu == (vx_enum)TIVX_CPU_ID_IPU1_0) || (self_cpu == (vx_enum)TIVX_CPU_ID_IPU1_1))
    if((self_cpu == (vx_enum)TIVX_CPU_ID_IPU1_1))
    {
        strncpy(target_name, TIVX_TARGET_SPIRX, TIVX_TARGET_MAX_NAME);
        vx_spirx_target_kernel = tivxAddTargetKernelByName(
                            TIVX_KERNEL_SPIRX_NAME,
                            target_name,
                            tivxspiRxProcess,
                            tivxspiRxCreate,
                            tivxspirxDelete,
                            tivxspirxControl,
                            NULL);

    }
}

void tivxRemoveTargetKernelSpiRx(void)
{
    vx_status status = (vx_status)VX_SUCCESS;

    status = tivxRemoveTargetKernel(vx_spirx_target_kernel);
    if(status == (vx_status)VX_SUCCESS)
    {
        vx_spirx_target_kernel = NULL;
    }

}


static vx_status VX_CALLBACK tivxspirxControl(
       tivx_target_kernel_instance kernel,
       uint32_t node_cmd_id, tivx_obj_desc_t *obj_desc[],
       uint16_t num_params, void *priv_arg)
{
    vx_status status = (vx_status)VX_SUCCESS;
    return status;
}


The app of SPI1 is as follows:

/*
 *
 * Copyright (c) 2017 Texas Instruments Incorporated
 *
 * All rights reserved not granted herein.
 *
 * Limited License.
 *
 * Texas Instruments Incorporated grants a world-wide, royalty-free, non-exclusive
 * license under copyrights and patents it now or hereafter owns or controls to make,
 * have made, use, import, offer to sell and sell ("Utilize") this software subject to the
 * terms herein.  With respect to the foregoing patent license, such license is granted
 * solely to the extent that any such patent is necessary to Utilize the software alone.
 * The patent license shall not apply to any combinations which include this software,
 * other than combinations with devices manufactured by or for TI ("TI Devices").
 * No hardware patent is licensed hereunder.
 *
 * Redistributions must preserve existing copyright notices and reproduce this license
 * (including the above copyright notice and the disclaimer and (if applicable) source
 * code license limitations below) in the documentation and/or other materials provided
 * with the distribution
 *
 * Redistribution and use in binary form, without modification, are permitted provided
 * that the following conditions are met:
 *
 * *       No reverse engineering, decompilation, or disassembly of this software is
 * permitted with respect to any software provided in binary form.
 *
 * *       any redistribution and use are licensed by TI for use only with TI Devices.
 *
 * *       Nothing shall obligate TI to provide you with source code for the software
 * licensed and provided to you in object code.
 *
 * If software source code is provided to you, modification and redistribution of the
 * source code are permitted provided that the following conditions are met:
 *
 * *       any redistribution and use of the source code, including any resulting derivative
 * works, are licensed by TI for use only with TI Devices.
 *
 * *       any redistribution and use of any object code compiled from the source code
 * and any resulting derivative works, are licensed by TI for use only with TI Devices.
 *
 * Neither the name of Texas Instruments Incorporated nor the names of its suppliers
 *
 * may be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * DISCLAIMER.
 *
 * THIS SOFTWARE IS PROVIDED BY TI AND TI'S LICENSORS "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 TI AND TI'S LICENSORS 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.
 *
 */

#include <TI/tivx.h>
#include <TI/j7.h>
#include <tivx_utils_file_rd_wr.h>
#include <TI/tivx_yh_pdd.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <assert.h>
#include <TI/tivx_task.h>
#include <TI/tivx_yh_pdd_spi.h>
#include <utils/iss/include/app_iss.h>
// #include <ti/drv/spi/MCSPI.h>
#include <sys/time.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <VX/vx_khr_pipelining.h>
#include <tivx_utils_file_rd_wr.h>
#include <pthread.h>

#define APP_SPI_RESULT_FIFO_NAME         "App_FifoSpiResult"
#define APP_MAX_FILE_PATH           (256u)
#define APP_ASSERT(x)               assert((x))
#define APP_ASSERT_VALID_REF(ref)   (APP_ASSERT(vxGetStatus((vx_reference)(ref))==VX_SUCCESS));
#define APP_BUFFFER_COUNT 64
typedef struct
{
    /** Type of message. */
    int         status;
    uint32_t    errcnt;    

} App_FifoSpiResult;

typedef struct {

    uint32_t stop_spi_task;
    uint32_t stop_spi_task_done;
    tivx_task task_spitx;
    tivx_task task_spirx;
    tivx_task task_spi_fifo_send;
    uint64_t spi_graph_run_cnt;
    uint64_t pre_spi_graph_run_cnt;
    int spi_status;
    uint32_t errcnt;
    uint32_t spiThreshold;
    tivx_mutex      mutex_spi_result;
    App_FifoSpiResult spiMsg;
    int fpsFifo_fd;
    vx_uint32 stop_task_spiFifo;

    /* config options */
    char input_file_1[APP_MAX_FILE_PATH];
    char input_file_2[APP_MAX_FILE_PATH];
    char output_file[APP_MAX_FILE_PATH];
    uint32_t width;
    uint32_t height;
    uint32_t is_tda4a;

    /* OpenVX references */
    vx_context context;
    vx_graph graph_rx;
    vx_graph graph_tx;
    vx_node  node;
    vx_node  node_rx;
    vx_image input_img1;
    vx_image input_img2;
    vx_image output_img;

    tivx_task task;
    tivx_spitx_params_t spitx_prms;
    tivx_spirx_params_t spirx_prms;
    tivx_spitx_sendSlamCarInfo_t spitx_data_local;
    tivx_spirx_recvSlamCarInfo_t spirx_data_local;
    vx_user_data_object spitx_config;
    vx_user_data_object spitx_data;
    vx_user_data_object spirx_config;
    vx_user_data_object spirx_data;

    tivx_spirx_recvSlamCarInfo_t spi_kernel_data;
    
} AppObj;

AppObj gAppObj;

pthread_cond_t  cond_funcA = PTHREAD_COND_INITIALIZER;
pthread_cond_t  cond_funcB = PTHREAD_COND_INITIALIZER;
pthread_cond_t  cond_funcC = PTHREAD_COND_INITIALIZER;
pthread_cond_t  cond_funcD = PTHREAD_COND_INITIALIZER;

pthread_mutex_t mutex_funcA = PTHREAD_MUTEX_INITIALIZER;//init mutex
pthread_mutex_t mutex_funcB = PTHREAD_MUTEX_INITIALIZER;//init mutex
pthread_mutex_t mutex_funcC = PTHREAD_MUTEX_INITIALIZER;//init mutex
pthread_mutex_t mutex_funcD = PTHREAD_MUTEX_INITIALIZER;//init mutex

static void app_parse_cmd_line_args(AppObj *obj, int argc, char *argv[]);
static void app_init(AppObj *obj);
static void app_deinit(AppObj *obj);
static vx_status app_create_graph(AppObj *obj);
static vx_status app_run_graph(AppObj *obj);
static void app_delete_graph(AppObj *obj);

#define APP_SPI_TASK_PERIOD_IN_10MS                  (1)
#define APP_LOSS_RATE_CALC_PERIOD_IN_MS             (1000)
#define APP_PPS_CHECK_PERIOD_IN_10MS                (150)
#define APP_FPS_CLEAR_PERIOD_IN_10MS                (500)

#define APP_GPIO_RESULT_SEND_PERIOD_IN_10MS                (10)
#define APP_TIMER_MAX_CNT                           (APP_LOSS_RATE_CALC_PERIOD_IN_MS * \
                                                        APP_PPS_CHECK_PERIOD_IN_10MS * \
                                                        APP_FPS_CLEAR_PERIOD_IN_10MS * \
                                                        APP_GPIO_RESULT_SEND_PERIOD_IN_10MS)


static void task_run_in_period(const char* taskName, uint32_t ms, pthread_cond_t  cond_func, pthread_mutex_t mutex_func,
struct timeval *oldtv, int *first_run_flg)
{
    struct timespec ts;
    struct timeval  curtv;
    u_int32_t        sec;
    unsigned long   micro;        
    pthread_mutex_lock(&mutex_func);
    if(!(*first_run_flg))
    {                
        /* timeout is expected to be in milli-sec. */
        micro = oldtv->tv_usec + (ms * 1000);
        sec   = oldtv->tv_sec;
        if (micro >= 1000000LLU)
        {
            sec   += micro/1000000LLU;
            micro %= 1000000LLU;
        }
        ts.tv_nsec = micro * 1000;
        ts.tv_sec  = sec;
        gettimeofday(&curtv, NULL);                
        if(((curtv.tv_sec==ts.tv_sec)&&(curtv.tv_usec>=ts.tv_nsec)) 
        || (curtv.tv_sec>ts.tv_sec))
        {
            VX_PRINT(VX_ZONE_ERROR, "%s task Timeout execution!\r\n", taskName);
        }
        else
        {                    
            pthread_cond_timedwait(&cond_func, &mutex_func, &ts);
        }
        gettimeofday(&curtv, NULL);  
        memcpy(oldtv, &curtv, sizeof(struct timeval));     
    }
    else
    {
        *first_run_flg = 0;    
        gettimeofday(oldtv, NULL); 
    }
    pthread_mutex_unlock(&mutex_func);    
}

static vx_status app_fifo_send(AppObj *obj)
{
    vx_status vxStatus = VX_SUCCESS;
    uint8_t *buf;
    struct timeval  oldtv;
    int first_run_flg = 1;
    while(1)
    {
        task_run_in_period("rx-app_fifo_send", 100, cond_funcB, mutex_funcB, &oldtv, &first_run_flg);
        tivxMutexLock(obj->mutex_spi_result);
        obj->spiMsg.status = obj->spi_status;
        obj->spiMsg.errcnt = obj->errcnt;        
        tivxMutexUnlock(obj->mutex_spi_result);

        buf = &obj->spiMsg;
        if(write(obj->fpsFifo_fd, buf, sizeof(App_FifoSpiResult)) < 0)  // 写入到FIFO中
        {
            perror("Write FIFO Failed");
        }
    }

    return vxStatus;
    
}


void app_spi_fifo_task(void *app_var)
{
    AppObj *obj = (AppObj *)app_var;
    vx_status status = VX_SUCCESS;

    // if (mkfifo(APP_SPI_RESULT_FIFO_NAME, 0666) < 0 ) // 创建FIFO管道
    //     perror("Create FIFO Failed");

    if((obj->fpsFifo_fd = open(APP_SPI_RESULT_FIFO_NAME, O_WRONLY)) < 0) // 以写打开一个FIFO 
    {
        perror("Open FIFO Failed");
    }

    while((!obj->stop_task_spiFifo) && (status == VX_SUCCESS))
    {

        status = app_fifo_send(obj);
    }
    close(obj->fpsFifo_fd);
    obj->stop_spi_task_done = 1;
}

static vx_status app_run_graph_spirx(AppObj *obj)
{
    vx_status status = VX_SUCCESS;
    uint8_t appCheckBuffer[APP_BUFFFER_COUNT];
    uint32_t i;

    for(i = 0; i < APP_BUFFFER_COUNT; i++){
        appCheckBuffer[i] = i;
    }
    // struct timespec ts;
    // struct timeval  tv;
    // u_int32_t        sec;
    // unsigned long   micro;

    while(1)
    {
        // pthread_mutex_lock(&mutex_funcC);
        // gettimeofday(&tv, NULL);
        // /* timeout is expected to be in milli-sec. */
        // micro = tv.tv_usec + (100 * 1000);
        // sec   = tv.tv_sec;

        // if (micro >= 1000000LLU)
        // {
        //     sec   += micro/1000000LLU;
        //     micro %= 1000000LLU;

        // }
        // ts.tv_nsec = micro * 1000;
        // ts.tv_sec  = sec;
        // pthread_cond_timedwait(&cond_funcC, &mutex_funcC, &ts);
        // gettimeofday(&tv, NULL);
        // pthread_mutex_unlock(&mutex_funcC);
        // vxVerifyGraph(obj->graph_rx);
        vxProcessGraph(obj->graph_rx);
                
        status = vxCopyUserDataObject(obj->spirx_data,
                                    0,
                                    sizeof(tivx_spirx_recvSlamCarInfo_t),
                                    &obj->spi_kernel_data,
                                    VX_READ_ONLY,
                                    VX_MEMORY_TYPE_HOST);

      
        // 对gpio状态进行判断,此时进行数据加锁
        tivxMutexLock(obj->mutex_spi_result);

        obj->spi_graph_run_cnt++;

        for(i = 0; i < APP_BUFFFER_COUNT; i++){
            // obj->spi_kernel_data.checkBuffer[i]
            // printf("obj->spi_kernel_data.checkBuffer[%d] = %d\n", i, obj->spi_kernel_data.checkBuffer[i]);
            if(appCheckBuffer[i] != obj->spi_kernel_data.checkBuffer[i])
            {
                obj->spiThreshold++;
                if(obj->spiThreshold > 3)
                {
                    obj->errcnt++;
                    obj->spi_status = 1;
                    VX_PRINT(VX_ZONE_ERROR, "spi graph recv err appCheckBuffer[%d] %d kernel_data[%d] %d status = %d \n", i, appCheckBuffer[i], i, obj->spi_kernel_data.checkBuffer[i], obj->spi_status);
                    VX_PRINT(VX_ZONE_ERROR, "increase spiThreshold count = %d\n", obj->spiThreshold);
                }
                VX_PRINT(VX_ZONE_ERROR, "==spi graph recv err appCheckBuffer[%d] %d kernel_data[%d] %d status = %d spiThreshold %d\n", i, appCheckBuffer[i], i, obj->spi_kernel_data.checkBuffer[i], obj->spi_status, obj->spiThreshold);
                break;  
            }
            else
            {
                obj->spiThreshold = 0;
                obj->spi_status = 0;
            }
        }
        if(obj->spi_status)
        {
            for(i = 0; i < APP_BUFFFER_COUNT; i++){
                printf("%d ", obj->spi_kernel_data.checkBuffer[i]);
            }
            printf("\r\n");
        }

        tivxMutexUnlock(obj->mutex_spi_result);
    }

    vxWaitGraph(obj->graph_rx);

    return status;
}


// static vx_status app_run_graph_spitx(AppObj *obj)
// {
//     vx_status status = VX_SUCCESS;
//     struct timespec ts;
//     struct timeval  tv;
//     u_int32_t        sec;
//     unsigned long   micro;

//     while(1)
//     {   
//         pthread_mutex_lock(&mutex_funcD);
//         gettimeofday(&tv, NULL);
//         /* timeout is expected to be in milli-sec. */
//         micro = tv.tv_usec + (APP_SPI_TASK_PERIOD_IN_10MS * 10 * 1000);
//         sec   = tv.tv_sec;

//         if (micro >= 1000000LLU)
//         {
//             sec   += micro/1000000LLU;
//             micro %= 1000000LLU;

//         }
//         ts.tv_nsec = micro * 1000;
//         ts.tv_sec  = sec;
//         pthread_cond_timedwait(&cond_funcD, &mutex_funcD, &ts);
//         gettimeofday(&tv, NULL);
//         pthread_mutex_unlock(&mutex_funcD);

//         vxProcessGraph(obj->graph_tx);
//         // VX_PRINT(VX_ZONE_ERROR, "app_run_graph_spitx test\r\n"); 

//     }

//     if(status == VX_SUCCESS)
//     {
//         status = vxWaitGraph(obj->graph_tx);
//     }
//     return status;
// }

void app_test_spirx_run_task(void *app_var)
{
    AppObj *obj = (AppObj *)app_var;

    // appPerfStatsCpuLoadResetAll();

    app_run_graph_spirx(obj);

    obj->stop_spi_task_done = 1;
}

// void app_test_spitx_run_task(void *app_var)
// {
//     AppObj *obj = (AppObj *)app_var;

//     // appPerfStatsCpuLoadResetAll();

//     app_run_graph_spitx(obj);

//     obj->stop_spi_task_done = 1;
// }

static int32_t app_run_task_create(AppObj *obj)
{
    int32_t status;
    tivx_task_create_params_t params;

    appPerfStatsCpuLoadResetAll();

    tivxTaskSetDefaultCreateParams(&params);
    params.task_main = app_test_spirx_run_task;
    params.priority = TIVX_TASK_PRI_LOWEST - 5;
    params.app_var = obj;
    obj->stop_spi_task_done = 0;
    obj->stop_spi_task = 0;
    status = tivxTaskCreate(&obj->task_spirx, &params);
    VX_PRINT(VX_ZONE_ERROR, "app_run_task_create close rx!!\r\n");  

    // tivxTaskSetDefaultCreateParams(&params);
    // params.task_main = app_test_spitx_run_task;
    // params.app_var = obj;
    // obj->stop_spi_task_done = 0;
    // obj->stop_spi_task = 0;
    // status = tivxTaskCreate(&obj->task_spitx, &params);


    tivxTaskSetDefaultCreateParams(&params);
    
    params.task_main = app_spi_fifo_task;
    params.app_var = obj;
    obj->stop_task_spiFifo = 0;
    obj->stop_spi_task = 0;
    status = tivxTaskCreate(&obj->task_spi_fifo_send, &params);

    return status;
}

void timer_10ms_handler(int m)
{
    static uint32_t cnt = 0;
    static uint32_t errflg = 0;
    // static int is_retained_cleared = 0;
    AppObj *obj = &gAppObj;

    if(0 == (cnt % (APP_SPI_TASK_PERIOD_IN_10MS * 5)))
    {
        tivxMutexLock(obj->mutex_spi_result);
        if(obj->pre_spi_graph_run_cnt == obj->spi_graph_run_cnt)
        {
            obj->errcnt++;
            errflg = 1;
            VX_PRINT(VX_ZONE_ERROR, "====1spi timer_10ms_handler spi_status 1\r\n");
        }
        else
        {
            if(errflg)
            {
                VX_PRINT(VX_ZONE_ERROR, "====2spi timer_10ms_handler spi_status 1\r\n");
                errflg = 0;
            }
        }
        obj->pre_spi_graph_run_cnt = obj->spi_graph_run_cnt;
        tivxMutexUnlock(obj->mutex_spi_result);
    }
    if(0 == (cnt % (1000)))
    {
        appPerfStatsPrintAll();
        VX_PRINT(VX_ZONE_ERROR, "====3spi timer_10ms_handler spi_status %d\r\n", obj->spi_status);  
    }
    if(cnt == APP_TIMER_MAX_CNT)
    {
        cnt = 0;
    }
    cnt++;
}

int app_test_spi_main(int argc, char* argv[])
{
    AppObj *obj = &gAppObj;

    struct timeval  oldtv;
    int first_run_flg = 1;

    app_parse_cmd_line_args(obj, argc, argv);
    
    app_init(obj);
    app_create_graph(obj);

    app_run_task_create(obj);
    obj->stop_task_spiFifo = 0;

    while(1)
    {
        task_run_in_period("rx-app_test_spi_main-timer_10ms_handler", 10, cond_funcA, mutex_funcA, &oldtv, &first_run_flg);
        timer_10ms_handler(0);
        // tivxEventWait(obj->evnt_master_pthread_run, TIVX_EVENT_TIMEOUT_WAIT_FOREVER);
    }

    // app_run_graph(obj);
    app_delete_graph(obj);
    app_deinit(obj);

    return 0;
}


static void app_init(AppObj *obj)
{
    obj->context = vxCreateContext();
    APP_ASSERT_VALID_REF(obj->context);
    tivxHwaLoadKernels(obj->context);
    tivxYhPddLoadKernels(obj->context);
    tivxMutexCreate(&obj->mutex_spi_result);
    // if(VX_SUCCESS != status)
    // {
    //     VX_PRINT(VX_ZONE_ERROR, "tivxMutexCreate create failed\n");
    //     return status;
    // }
    // appSensorPowerOn();
}

static void app_deinit(AppObj *obj)
{
    vxReleaseContext(&obj->context);
}

static vx_status app_create_graph(AppObj *obj)
{
    vx_status status = VX_SUCCESS;

    obj->graph_rx = vxCreateGraph(obj->context);
    APP_ASSERT_VALID_REF(obj->graph_rx);
    // obj->graph_tx = vxCreateGraph(obj->context);
    // APP_ASSERT_VALID_REF(obj->graph_tx);

    
    // obj->spitx_config = vxCreateUserDataObject(obj->context, "tivx_spitx_params_t", sizeof(tivx_spitx_params_t), &obj->spitx_prms);
    // obj->spitx_data = vxCreateUserDataObject(obj->context, "tivx_spitx_sendSlamCarInfo_t", sizeof(tivx_spitx_sendSlamCarInfo_t), &obj->spitx_data_local);

    obj->spirx_config = vxCreateUserDataObject(obj->context, "tivx_spirx_params_t", sizeof(tivx_spirx_params_t), &obj->spirx_prms);
    obj->spirx_data = vxCreateUserDataObject(obj->context, "tivx_spirx_recvSlamCarInfo_t", sizeof(tivx_spirx_recvSlamCarInfo_t), &obj->spirx_data_local);

    obj->node_rx = tivxSpirxNode(obj->graph_rx,
                              obj->spirx_config,
                              obj->spirx_data);
    APP_ASSERT_VALID_REF(obj->node_rx);
    status = vxSetNodeTarget(obj->node_rx, VX_TARGET_STRING, TIVX_TARGET_SPIRX);
    APP_ASSERT(status==VX_SUCCESS);
    vxVerifyGraph(obj->graph_rx);
    vxSetReferenceName((vx_reference)obj->node_rx, "spirx");
    status = tivxExportGraphToDot(obj->graph_rx,".", "vx_app_spirx_test");

    


    // printf("tivxspitxNode  \n");
    // obj->node = tivxSpitxNode(obj->graph_tx,
    //                           obj->spitx_config,
    //                           obj->spitx_data);
    // printf("tivxSpitxNode  ok\n");

    // APP_ASSERT_VALID_REF(obj->node);

    // status = vxSetNodeTarget(obj->node, VX_TARGET_STRING, TIVX_TARGET_SPITX);
    // APP_ASSERT(status==VX_SUCCESS);
    
    // vxVerifyGraph(obj->graph_tx);

    // vxSetReferenceName((vx_reference)obj->node, "spitx");
    // // APP_ASSERT(status==VX_SUCCESS);

    // status = tivxExportGraphToDot(obj->graph_tx,".", "vx_app_spitx_test");
    

    /* APP_ASSERT(status==VX_SUCCESS); */ /* dont assert on this error since its not critical */

    return status;
}

static void app_delete_graph(AppObj *obj)
{
    vxReleaseNode(&obj->node);
    vxReleaseGraph(&obj->graph_tx);
    vxReleaseUserDataObject(&obj->spitx_config);
    vxReleaseUserDataObject(&obj->spitx_data);
}


// static vx_status app_run_graph(AppObj *obj)
// {
//     vx_status status = VX_SUCCESS;
//     int i = 0;

//     printf(" Running graph ...\n");
//     for(i = 0; i < 0xFFFFFFF; i++)
//     {    
//         status = vxScheduleGraph(obj->graph);
//         APP_ASSERT(status==VX_SUCCESS);
//         status = vxWaitGraph(obj->graph);
//         APP_ASSERT(status==VX_SUCCESS);

//     }

//     return status;
// }

static void app_show_usage(int argc, char* argv[])
{
    printf("\n");
    printf(" C7x Kernel Demo - (c) Texas Instruments 2018\n");
    printf(" ========================================================\n");
    printf("\n");
    printf(" Usage,\n");
    printf("  %s --cfg <config file>\n", argv[0]);
    printf("\n");
}

static void app_set_cfg_default(AppObj *obj)
{
    snprintf(obj->input_file_1,APP_MAX_FILE_PATH, "./img_1.bmp");
    snprintf(obj->input_file_2,APP_MAX_FILE_PATH, "./img_2.bmp");
    snprintf(obj->output_file,APP_MAX_FILE_PATH, "./out_img.bmp");
    obj->width = 640;
    obj->height = 480;
}

static void app_parse_cfg_file(AppObj *obj, char *cfg_file_name)
{
    FILE *fp = fopen(cfg_file_name, "r");
    char line_str[1024];
    char *token;

    if(fp==NULL)
    {
        printf("# ERROR: Unable to open config file [%s]\n", cfg_file_name);
        exit(0);
    }

    while(fgets(line_str, sizeof(line_str), fp)!=NULL)
    {
        char s[]=" \t";

        if (strchr(line_str, '#'))
        {
            continue;
        }

        /* get the first token */
        token = strtok(line_str, s);
        if(strcmp(token, "input_file_1")==0)
        {
            token = strtok(NULL, s);
            token[strlen(token)-1]=0;
            strcpy(obj->input_file_1, token);
        }
        else
        if(strcmp(token, "input_file_2")==0)
        {
            token = strtok(NULL, s);
            token[strlen(token)-1]=0;
            strcpy(obj->input_file_2, token);
        }
        else
        if(strcmp(token, "output_file")==0)
        {
            token = strtok(NULL, s);
            token[strlen(token)-1]=0;
            strcpy(obj->output_file, token);
        }
        else
        if(strcmp(token, "width")==0)
        {
            token = strtok(NULL, s);
            obj->width = atoi(token);
        }
        else
        if(strcmp(token, "height")==0)
        {
            token = strtok(NULL, s);
            obj->height = atoi(token);
        }
        else
        if(strcmp(token, "is_tda4a")==0)
        {
            token = strtok(NULL, s);
            obj->is_tda4a = atoi(token);
            obj->spitx_prms.is_tda4a = atoi(token);
            obj->spirx_prms.is_tda4a = atoi(token);
        }   
    }

    fclose(fp);
}

static void app_parse_cmd_line_args(AppObj *obj, int argc, char *argv[])
{
    int i;

    app_set_cfg_default(obj);

    if(argc==1)
    {
        app_show_usage(argc, argv);
        exit(0);
    }

    for(i=0; i<argc; i++)
    {
        if(strcmp(argv[i], "--cfg")==0)
        {
            i++;
            if(i>=argc)
            {
                app_show_usage(argc, argv);
            }
            app_parse_cfg_file(obj, argv[i]);
            break;
        }
        else
        if(strcmp(argv[i], "--help")==0)
        {
            app_show_usage(argc, argv);
            exit(0);
        }
    }
}

We try to use CCS to trace the hardware interrupt function MCSPI_v1_hwiFxn corresponding to SPI1, but when SPI1 receives data normally, it cannot be traced in a single step, let alone the situation when SPI1 receives data abnormally. what should we do? Can you help us analyze the above situation and provide us with some ideas to solve the problem, or tell us how to use CCS to track the problem? 

By the way, we use SDK7.1, and our hardware version is es1.0.

In order to confirm whether the receiving buffer of SPI1 can still work normally, we try to read the data in the buffer by k3conf read buffer_addr, but we don't know what the specific buffer_addr should be?

it seems buffer_addr=0x0211 0150 as the TRM file shown as fellow, but we want to read all the 64 bytes data, how could we do?

Regards,

Jason

  • Hi Tiers,

          Base on the second abnormal condition what we mentioned above, we use the while statement polling method to replace the event triggering method. As shown in the following code base on vx_spirx_target.c file before

         

    diff --git a/r5f/vx_spirx_target.c b/r5f/vx_spirx_target.c
    index bc53ea0..973f9f3 100644
    --- a/r5f/vx_spirx_target.c
    +++ b/r5f/vx_spirx_target.c
    @@ -438,9 +438,12 @@ static bool SPI_mst_slv_xfer(void *spi, SPI_ConfigEx *test, uint32_t xferLen, ui
     
     
     #define SPIRX_TARGET_RX_DATA_EVENT     (Event_Id_00)
    -
    +static uint32_t spiRxEvent = 0;
    +static uint32_t spiRxEventCnt = 0;
     void MCSPI_transferCallback(MCSPI_Handle mcHandle, SPI_Transaction *transaction){
    -    Event_post(gSpirxIntrEvent, SPIRX_TARGET_RX_DATA_EVENT);
    +    // Event_post(gSpirxIntrEvent, SPIRX_TARGET_RX_DATA_EVENT);
    +    spiRxEvent = 1;
    +    spiRxEventCnt++;
     }
     
     static void mcSpiInit(uint32_t instance, MCSPI_Params *spiParams){
    @@ -535,8 +538,9 @@ static vx_status VX_CALLBACK tivxspiRxProcess(
         // vx_uint32 size;
         tivx_spirx_recvSlamCarInfo_t *mspiRecvData; 
         tivx_obj_desc_user_data_object_t *src_desc0;
    -    UInt postedEvents;
    -    
    +    uint16_t i = 0;
    +    // UInt postedEvents;
    +    // SPI_v1_HWAttrs const *hwAttrs;
         if ( (num_params != TIVX_KERNEL_SPIRX_MAX_PARAMS)
             || (NULL == obj_desc[TIVX_KERNEL_SPIRX_INPUT_CFG_IDX])
             || (NULL == obj_desc[TIVX_KERNEL_SPIRX_OUTPUT_DATA_IDX])
    @@ -564,14 +568,22 @@ static vx_status VX_CALLBACK tivxspiRxProcess(
                 VX_PRINT(VX_ZONE_ERROR,"Error transfer SPI\n");
                 printf("mspiRecvData = %d\n", mspiRecvData->pdvSpiStatus);
             }
    -
    -        postedEvents = Event_pend(gSpirxIntrEvent,0,
    -                            SPIRX_TARGET_RX_DATA_EVENT,
    -                            BIOS_WAIT_FOREVER);
    -
    -        if(postedEvents & SPIRX_TARGET_RX_DATA_EVENT){
    +        // hwAttrs = (const SPI_v1_HWAttrs *)spi->handle->hwAttrs;
    +        VX_PRINT(VX_ZONE_ERROR, "step 0 \n");
    +        while((spiRxEvent == 0) && (i++ < 100))
    +        {
    +            tivxTaskWaitMsecs(1);
    +        };
    +        i = 0;
    +        spiRxEvent = 0;
    +        VX_PRINT(VX_ZONE_ERROR, "step 1 Cnt %d\n", spiRxEventCnt);
    +        // postedEvents = Event_pend(gSpirxIntrEvent,0,
    +        //                     SPIRX_TARGET_RX_DATA_EVENT,
    +        //                     BIOS_WAIT_FOREVER);
    +
    +        // if(postedEvents & SPIRX_TARGET_RX_DATA_EVENT){
           
    -        }
    +        // }
             // tivxTaskWaitMsecs(1);
     
             tivxMemBufferUnmap(src_desc0_target_ptr, src_desc0->mem_size, VX_MEMORY_TYPE_HOST, VX_WRITE_ONLY);

          the problem is found that the interrupt callback function cannot be triggered continuously. After 1048 seconds of normal operation, the SPI1 receiving interrupt cannot be triggered again, however, there is still data sent from the MCU on the SPI1 bus. What is the reason for this?

    Regards,

    Jason

  • Hi Jason,

    Couple of questions,

    1, Do you use SPI in DMA mode?

    2, I guess OpenVX and SPI are running on separate tasks, just wondering why SPI interrupt is affecting OpenVX graph? Why ProcessGraph is getting stalled? Are they both waiting for each other? 

    3, Can you please check the interrupt status and enable register to confirm that interrupt is still enabled and if there is any pending interrupt? 

    4, Can you please add some counters/debug code in the code to check if it has really missing interrupt or if it is somethings else?

    Regards,

    Brijesh

  • Hi Brijesh,

         1.we don't use SPI in DMA mode, how to use the DMA mode?

         2.Because we used the event waiting method at the beginning, the event signal was not sent because the interrupt was not generated at this time, resulting in the tivxspiRxProcess function in a blocking state, and the OpenVX graph calls the tivxspiRxProcess function at the application layer, thus causing blocking.

         3.I will try to check it, but where are the interrupt status and enable register? Could I read them by "k3conf read address"?

         4.I add spiRxEventCnt in function MCSPI_transferCallback, and found that it hadn't increased after the spi received abnormal.

    Regards,

    Jason

  • Hi Jason,

    ok, no need to check if DMA is not explicitly enabled.

    can you try using polling mode and see it works?

    Also does it occur on the first frame itself or after sometime? I am trying to see if there is any conflict?

    Also which McSPI  instance are you using?

    Regards,

    Brijesh

  • Hi Brijesh,

             I mentioned this in my reply a few days ago, as shown in the figure below, I've try polling mode and the interrupt doesn't work after 1048s(Faster than using event mode when errors occur), it didn't occur on the first frame itself, we use McSPI0 to transfer data to mcu, and use McSPI1 to receive data from mcu, and now the McSPI1 receive abnormal.


    I guess it is due to the delay caused by the slow response to the interrupt each time, and then gradually accumulates, and finally cannot respond to the interrupt again? Because poll mode is obviously slower than event mode, and I think maybe DMA mode will be faster than the above two modes, will it solve this problem, but I don’t know how to use it now.

    Regards,

    Jason

        

  • Hi Jason,

    I was not asking for this polling mode.

    Can you set the MCSPI_Params.transferMode to SPI_MODE_BLOCKING and hwAttrs.enableIntr flag to FALSE. This will change operating mode to polling the McSPI driver.

    Regards,

    Brijesh

  • Hi Brijesh,

           Sorry, it took a long time to reply to you. I set the MCSPI_Params.transferMode to SPI_MODE_BLOCKING and hwAttrs.enableIntr flag to FALSE, then it used polling mode, but it can't not receive SPI data again. Then I set the MCSPI_Params.transferMode to SPI_MODE_BLOCKING and hwAttrs.enableIntr flag to TRUE, so it used blocking mode, we must delete Event_pend in tivxspiRxProcess function, it could work normal for about 1000s, then could not receive SPI data again. It seems worse than callback mode.

    Regards,

    Jason

  • Hi Jason,

    Sorry, did not get this statement "we must delete Event_pend in tivxspiRxProcess". I dont see there s any OpenVX node for SPI RX in the released code. Is it something that you have added? Is there something missing in OpenVX node implementation? 

    Is it possible to check this using simple standalone PDK example? or is it possible to share this OpenVX node implementation for the review?

    Regards,

    Brijesh

  • Hi Brijesh,

          You can see tivxspiRxProcess function in vx_spirx_target.c, because we use SPI_MODE_BLOCKING  mode, so it can't produce interrupt again, but we use Event_post in interrupt callback function before, the Event_pend depend on Event_post, so it would never be triggered, so it should be delete in tivxspiRxProcess function. We add rx node in app_create_graph function:

    static vx_status app_create_graph(AppObj *obj)
    {
    vx_status status = VX_SUCCESS;

    obj->graph_rx = vxCreateGraph(obj->context);
    APP_ASSERT_VALID_REF(obj->graph_rx);
    // obj->graph_tx = vxCreateGraph(obj->context);
    // APP_ASSERT_VALID_REF(obj->graph_tx);


    // obj->spitx_config = vxCreateUserDataObject(obj->context, "tivx_spitx_params_t", sizeof(tivx_spitx_params_t), &obj->spitx_prms);
    // obj->spitx_data = vxCreateUserDataObject(obj->context, "tivx_spitx_sendSlamCarInfo_t", sizeof(tivx_spitx_sendSlamCarInfo_t), &obj->spitx_data_local);

    obj->spirx_config = vxCreateUserDataObject(obj->context, "tivx_spirx_params_t", sizeof(tivx_spirx_params_t), &obj->spirx_prms);
    obj->spirx_data = vxCreateUserDataObject(obj->context, "tivx_spirx_recvSlamCarInfo_t", sizeof(tivx_spirx_recvSlamCarInfo_t), &obj->spirx_data_local);

    obj->node_rx = tivxSpirxNode(obj->graph_rx,
    obj->spirx_config,
    obj->spirx_data);
    APP_ASSERT_VALID_REF(obj->node_rx);
    status = vxSetNodeTarget(obj->node_rx, VX_TARGET_STRING, TIVX_TARGET_SPIRX);
    APP_ASSERT(status==VX_SUCCESS);
    vxVerifyGraph(obj->graph_rx);
    vxSetReferenceName((vx_reference)obj->node_rx, "spirx");
    status = tivxExportGraphToDot(obj->graph_rx,".", "vx_app_spirx_test");


    // printf("tivxspitxNode \n");
    // obj->node = tivxSpitxNode(obj->graph_tx,
    // obj->spitx_config,
    // obj->spitx_data);
    // printf("tivxSpitxNode ok\n");

    // APP_ASSERT_VALID_REF(obj->node);

    // status = vxSetNodeTarget(obj->node, VX_TARGET_STRING, TIVX_TARGET_SPITX);
    // APP_ASSERT(status==VX_SUCCESS);

    // vxVerifyGraph(obj->graph_tx);

    // vxSetReferenceName((vx_reference)obj->node, "spitx");
    // // APP_ASSERT(status==VX_SUCCESS);

    // status = tivxExportGraphToDot(obj->graph_tx,".", "vx_app_spitx_test");

    /* APP_ASSERT(status==VX_SUCCESS); */ /* dont assert on this error since its not critical */

    return status;
    }

    Regards,

    Jason

  • Hi Jason,

    I don't see this OpenVX node supported in the standard PSDKRA7.3 release. I am not sure from where you get it. 

    Could you please share this code for the review? 

    Regards,

    Brijesh

  • Hi Brijesh,

          The driver of spi is ~/ti-processor-sdk-rtos-j721e-evm-07_01_00_11/pdk_jacinto_07_01_00_45/packages/ti/drv/spi/src/v1/SPI_v1.c, as fellow:

    /**
     *  \file   SPI_v1.c
     *
     *  \brief  MCSPI IP V1 specific driver implementation.
     *
     *   This file contains the driver APIs for SPI.
     */
    
    /*
     * Copyright (c) 2014-2019, 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.
     */
    
    #include <string.h>
    #include <stdint.h>
    #include <stdbool.h>
    #include <ti/drv/spi/MCSPI.h>
    #include <ti/drv/spi/soc/SPI_v1.h>
    #include <ti/csl/src/ip/mcspi/V0/mcspi.h>
    #include <ti/csl/src/ip/mcspi/V0/hw_mcspi.h>
    #include <ti/drv/spi/src/SPI_osal.h>
    #include <stdio.h>
    
    #ifdef __GNUC__
    #pragma GCC diagnostic ignored "-Wunused-local-typedefs"
    #endif
    
    #define SPI_PARAMS_SIZE               (32U)
    
    #define MCSPI_TX_RX_FIFO_OFFSET       (4U)
    
    #define MCSPI_POLLING_TIMEOUT_LOOP    (1000U)
    
    /* SPI functions */
    static void          SPI_close_v1(SPI_Handle handle);
    static void          SPI_init_v1(SPI_Handle handle);
    static SPI_Handle    SPI_open_v1(SPI_Handle handle, const SPI_Params *params);
    static bool          SPI_transfer_v1(SPI_Handle handle,
                                         SPI_Transaction *transaction);
    static void          SPI_transferCancel_v1(SPI_Handle handle);
    static int32_t       SPI_control_v1(SPI_Handle handle, uint32_t cmd, const void *arg);
    
    /* MCSPI functions */
    static void          MCSPI_close_v1(MCSPI_Handle mcHandle);
    static void          MCSPI_init_v1(MCSPI_Handle mcHandle);
    static MCSPI_Handle  MCSPI_open_v1(MCSPI_Handle mcHandle, const MCSPI_Params *params);
    static bool          MCSPI_transfer_v1(MCSPI_Handle mcHandle,
                                           SPI_Transaction *transaction);
    static void          MCSPI_transferCancel_v1(MCSPI_Handle mcHandle);
    static int32_t       MCSPI_control_v1(MCSPI_Handle mcHandle, uint32_t cmd, const void *arg);
    
    static MCSPI_Handle  MCSPI_get_handle(SPI_Handle handle);
    static void          MCSPI_get_params(const SPI_Params *params, MCSPI_Params *mcParams);
    
    /* SPI function table for SPI_v1 implementation */
    const SPI_FxnTable SPI_FxnTable_v1 = {
        &SPI_close_v1,
        &SPI_control_v1,
        &SPI_init_v1,
        &SPI_open_v1,
        &SPI_transfer_v1,
        &SPI_transferCancel_v1,
        NULL
    };
    
    /* MCSPI function table for MCSPI_v1 implementation */
    const MCSPI_FxnTable MCSPI_FxnTable_v1 =
    {
        &MCSPI_close_v1,
        &MCSPI_control_v1,
        &MCSPI_init_v1,
        &MCSPI_open_v1,
        &MCSPI_transfer_v1,
        &MCSPI_transferCancel_v1
    };
    
    /*
     *  ======== MCSPI_get_handle ========
     *  @pre    Function assumes that the handle is not NULL
     */
    static MCSPI_Handle MCSPI_get_handle(SPI_Handle handle)
    {
        MCSPI_Handle          mcHandle = NULL;
        SPI_v1_HWAttrs const *hwAttrs;
        uint32_t              chNum;
        uint32_t              i;
    
        hwAttrs = (const SPI_v1_HWAttrs *)handle->hwAttrs;
        chNum   = hwAttrs->chNum;
    
        for (i = 0; i < MCSPI_MAX_NUM_INSTANCES; i++)
        {
            if(MCSPI_config[i][chNum].handle == handle)
            {
                mcHandle = (MCSPI_Handle)&(MCSPI_config[i][chNum]);
                break;
            }
        }
    
        return (mcHandle);
    }
    
    /*
     *  ======== SPI_close_v1 ========
     *  @pre    Function assumes that the handle is not NULL
     */
    static void SPI_close_v1(SPI_Handle handle)
    {
        SPI_v1_Object   *object;
    
        /* Input parameter validation */
        if (handle != NULL)
        {
            /* Get the pointer to the object */
            object = (SPI_v1_Object*)handle->object;
    
            MCSPI_close_v1(object->mcHandle);
    
            object->mcHandle = NULL;
        }
    }
    
    /*
     *  ======== SPI_init_v1 ========
     *  @pre    Function assumes that the handle is not NULL
     */
    static void SPI_init_v1(SPI_Handle handle)
    {
        MCSPI_Handle     mcHandle;
        SPI_v1_Object   *object;
    
        /* Input parameter validation */
        if (handle != NULL)
        {
            object = (SPI_v1_Object*)handle->object;
    
            /* Get multi-channel handle */
            mcHandle = MCSPI_get_handle(handle);
            if (mcHandle != NULL)
            {
                MCSPI_init_v1(mcHandle);
            }
    
            /* initialize object varibles */
            object->hwi                 = NULL;
            object->mutex               = NULL;
            object->transferComplete    = NULL;
            object->transferCallbackFxn = NULL;
            object->chOpenedCnt         = 0;
        }
    }
    
    /*
     *  ======== SPI_open_v1 ========
     *  @pre    Function assumes that the handle is not NULL
     */
    static SPI_Handle SPI_open_v1(SPI_Handle handle, const SPI_Params *params)
    {
        MCSPI_Handle          mcHandle;
        MCSPI_Params          mcParams;
        SPI_v1_Object        *object;
    
        /* Input parameter validation */
        if (handle != NULL)
        {
            /* Get the pointer to the object */
            object = (SPI_v1_Object*)handle->object;
    
            /* Get multi-channel handle */
            mcHandle = MCSPI_get_handle(handle);
            if (mcHandle != NULL)
            {
                if (params != NULL)
                {
                    /* covert SPI_Params to MCSPI_Params */
                    MCSPI_get_params(params, &mcParams);
    
                    /* save the transferCallbackFxn in SPI_Params */
                    object->transferCallbackFxn = params->transferCallbackFxn;
                }
                mcHandle = MCSPI_open_v1(mcHandle, &mcParams);
                if (mcHandle != NULL)
                {
                    object->mcHandle = mcHandle;
                }
                else
                {
                    object->mcHandle = NULL;
                }
            }
        }
    
        return (handle);
    }
    
    /*
     *  ======== SPI_transfer_v1 ========
     *  @pre    Function assumes that handle and transaction is not NULL
     */
    static bool SPI_transfer_v1(SPI_Handle handle, SPI_Transaction *transaction)
    {
        MCSPI_Handle   mcHandle;
        bool           ret_val = (bool)false;
    
        /* Input parameter validation */
        if ((handle != NULL) && (transaction != NULL))
        {
            /* Get multi-channel handle */
            mcHandle = MCSPI_get_handle(handle);
            if (mcHandle != NULL)
            {
                ret_val = MCSPI_transfer_v1(mcHandle, transaction);
            }
        }
    
        return (ret_val);
    }
    
    
    /*
     *  ======== SPI_transferCancel_v1 ========
     */
    static void SPI_transferCancel_v1(SPI_Handle handle)
    {
        MCSPI_Handle   mcHandle;
    
        /* Input parameter validation */
        if (handle != NULL)
        {
            /* Get multi-channel handle */
            mcHandle = MCSPI_get_handle(handle);
            if (mcHandle != NULL)
            {
                MCSPI_transferCancel_v1(mcHandle);
            }
        }
        return;
    }
    
    /*
     *  ======== SPI_control_v1 ========
     */
    static int32_t SPI_control_v1(SPI_Handle handle, uint32_t cmd, const void *arg)
    {
        MCSPI_Handle   mcHandle;
        int32_t        ret_val = SPI_STATUS_ERROR;
    
        /* Input parameter validation */
        if (handle != NULL)
        {
            /* Get multi-channel handle */
            mcHandle = MCSPI_get_handle(handle);
            if (mcHandle != NULL)
            {
                ret_val = MCSPI_control_v1(mcHandle, cmd, arg);
            }
        }
    
        return ret_val;
    }
    
    /*
     *  ======== MCSPI_get_params ========
     *  @pre    Function assumes that params and mcParams are not NULL
     */
    static void MCSPI_get_params(const SPI_Params *params, MCSPI_Params *mcParams)
    {
        mcParams->transferMode        = params->transferMode;
        mcParams->transferTimeout     = params->transferTimeout;
        mcParams->transferCallbackFxn = NULL;
        mcParams->mode                = params->mode;
        mcParams->bitRate             = params->bitRate;
        mcParams->dataSize            = params->dataSize;
        mcParams->frameFormat         = params->frameFormat;
        mcParams->custom              = params->custom;
    
        return;
    }
    
    /*
     *  ======== MCSPI_close_v1 ========
     *  @pre    Function assumes that the handle is not NULL
     */
    static void MCSPI_close_v1(MCSPI_Handle mcHandle)
    {
        SPI_Handle            handle;
        SPI_v1_Object        *object;
        SPI_v1_HWAttrs const *hwAttrs;
        SPI_v1_chObject      *chObj;
        uint32_t              chNum;
    
        /* Input parameter validation */
        if (mcHandle != NULL)
        {
        /* Get SPI handle and channel */
        handle  = mcHandle->handle;
        chNum   = mcHandle->chnNum;
        hwAttrs = (const SPI_v1_HWAttrs *)handle->hwAttrs;
    
        /* Get the pointer to the instance object and channel object */
        object = (SPI_v1_Object*)handle->object;
        chObj   = &(object->chObject[chNum]);
    
        MCSPI_init_v1(mcHandle);
    
        object->chOpenedCnt--;
        if (object->chOpenedCnt == 0U)
        {
            if(object->transferComplete != NULL)
            {
                /* Destruct the semaphore */
                (void)SPI_osalDeleteBlockingLock(object->transferComplete);
                object->transferComplete = NULL;
            }
    
            /* All the channels closed */
            if(object->hwi != NULL)
            {
                /* Destruct the Hwi */
                (void)SPI_osalHardwareIntDestruct(object->hwi, (int32_t)hwAttrs->eventId);
                object->hwi = NULL;
            }
    
            if(object->mutex != NULL)
            {
                /* Destruct the instance lock */
                (void)SPI_osalDeleteBlockingLock(object->mutex);
                object->mutex = NULL;
            }
    
            object->mcHandle = NULL;
            object->transferCallbackFxn = NULL;
        }
    
    #ifdef SPI_DMA_ENABLE
        if (hwAttrs->dmaMode == (bool)true)
        {
            MCSPI_dmaFreeChannel(mcHandle);
        }
    #endif
    
        chObj->isOpen = (bool)false;
        }
    }
    /* Get recieved data from the RX FIFO based on the data size */
    
    /*
     *  ======== MCSPI_receiveData_v1 ========
     *  
     *  Get recieved data words from the RX FIFO based on the data size
     *
     *  if dataSize <= 8 bits, read 8-bit word from RX FIFO,
     *  if 8 bits < dataSize <= 16 bits, read 16-bit word from RX FIFO,
     *  if 16 bits < dataSize <= 32 bits, read 32-bit word from RX FIFO,
     */
    static void *MCSPI_receiveData_v1 (uint32_t baseAddr, uint32_t dataSize, void *dataBuf, uint32_t chNum);  /*for misra warnings*/
    static void *MCSPI_receiveData_v1 (uint32_t baseAddr, uint32_t dataSize, void *dataBuf, uint32_t chNum)
    {
        void *dataPtr;
    
        if (dataSize <= 8U)
        {
            *(uint8_t *)dataBuf = (uint8_t)McSPIReceiveData(baseAddr, chNum);
            dataPtr = (void *)(((uint8_t *)dataBuf) + 1U);
        }
        else if (dataSize <= 16U)
        {
            *(uint16_t *)dataBuf = (uint16_t)McSPIReceiveData(baseAddr, chNum);
            dataPtr = (void *)(((uint8_t *)dataBuf) + 2U);
        }
        else
        {
            *(uint32_t *)dataBuf = (uint32_t)McSPIReceiveData(baseAddr, chNum);
            dataPtr = (void *)(((uint8_t *)dataBuf) + 4U);
        }
    
        return (dataPtr);
    }
    
    /*
     *  ======== MCSPI_transmitData_v1 ========
     *  
     *  Put data to the TX FIFO based on the data size (in # of bits)
     *
     *  if dataSize <= 8 bits, write 8-bit word to TX FIFO,
     *  if 8 bits < dataSize <= 16 bits, write 16-bit word to TX FIFO,
     *  if 16 bits < dataSize <= 32 bits, write 32-bit word to TX FIFO,
     */
    void *MCSPI_transmitData_v1 (uint32_t baseAddr, uint32_t dataSize, void *dataBuf, uint32_t chNum);  /*for misra warnings*/
    void *MCSPI_transmitData_v1 (uint32_t baseAddr, uint32_t dataSize, void *dataBuf, uint32_t chNum)
    {
        void *dataPtr;
    
        if (dataSize <= 8U)
        {
            McSPITransmitData(baseAddr, (uint32_t)(*(uint8_t *)dataBuf), chNum);
            dataPtr = (void *)(((uint8_t *)dataBuf) + 1U);
        }
        else if (dataSize <= 16U)
        {
            McSPITransmitData(baseAddr, (uint32_t)(*(uint16_t *)dataBuf), chNum);
            dataPtr = (void *)(((uint8_t *)dataBuf) + 2U);
        }
        else
        {
            McSPITransmitData(baseAddr, *(uint32_t *)dataBuf, chNum);
            dataPtr = (void *)(((uint8_t *)dataBuf) + 4U);
        }
    
        return (dataPtr);
    }
    
    /*
     *  ======== MCSPI_xferSetup_v1 ========
     *  This functions configures the transfer mode (RX/TX, RX only or TX only)
     *  and setup the TX/RX FIFO trigger level when FIFO mode is enabled
     */
    void MCSPI_xferSetup_v1(MCSPI_Handle mcHandle, SPI_Transaction *transaction);  /*for misra warnings*/
    void MCSPI_xferSetup_v1(MCSPI_Handle mcHandle, SPI_Transaction *transaction)
    {
        SPI_Handle            handle;
        SPI_v1_Object        *object;
        SPI_v1_chObject      *chObj;
        uint32_t              chNum;
        SPI_v1_HWAttrs const *hwAttrs;
        SPI_v1_ChnCfg const  *chnCfg;
        uint32_t              transBytes=0;
        uint32_t              txFifo;
        uint32_t              rxFifo;
        uint32_t              countIndex;
        uint32_t              wordCount;
    
        /* Get the pointer to the object and hwAttrs */
        handle  = mcHandle->handle;
        chNum   = mcHandle->chnNum;
        object = (SPI_v1_Object *)handle->object;
        chObj   = &(object->chObject[chNum]);
        hwAttrs = (const SPI_v1_HWAttrs *)handle->hwAttrs;
        chnCfg  = &(hwAttrs->chnCfg[chNum]);
    
        if (chnCfg->trMode == MCSPI_RX_ONLY_MODE)
        {
            chObj->writeBufIdx = NULL;
            chObj->writeCountIdx = 0;
        }
        else
        {
            chObj->writeBufIdx = (void *)transaction->txBuf;
            if (chObj->writeBufIdx != NULL)
            {
                chObj->writeCountIdx = (uint32_t)transaction->count;
            }
            else
            {
                chObj->writeCountIdx = 0;
            }
        }
    
        if (chnCfg->trMode == MCSPI_TX_ONLY_MODE)
        {
            chObj->readBufIdx = NULL;
            chObj->readCountIdx = 0;
        }
        else
        {
            chObj->readBufIdx = (void *)transaction->rxBuf;
            if (chObj->readBufIdx != NULL)
            {
                chObj->readCountIdx = (uint32_t)transaction->count;
            }
            else
            {
                chObj->readCountIdx = 0;
            }
        }
    
        /* Enable FIFO's dependent on which mode of operation is chosen */
        if (chnCfg->trMode == MCSPI_TX_RX_MODE)
        {
            if ((hwAttrs->txTrigLvl == 0U) || (hwAttrs->rxTrigLvl == 0U))
            {
                txFifo = MCSPI_TX_FIFO_DISABLE;
                rxFifo = MCSPI_RX_FIFO_DISABLE;
                object->fifoSize = 0;
            }
            else
            {
                txFifo = MCSPI_TX_FIFO_ENABLE;
                rxFifo = MCSPI_RX_FIFO_ENABLE;
                object->fifoSize = MCSPI_RX_TX_FIFO_SIZE;
            }
        }
        else if (chnCfg->trMode == MCSPI_TX_ONLY_MODE)
        {
            /* TX_ONLY Mode */
            if (hwAttrs->txTrigLvl == 0U)
            {
                txFifo = MCSPI_TX_FIFO_DISABLE;
                object->fifoSize = 0;
            }
            else
            {
                txFifo = MCSPI_TX_FIFO_ENABLE;
                object->fifoSize = MCSPI_FULL_FIFO_SIZE;
            }
            rxFifo = MCSPI_RX_FIFO_DISABLE;
        }
        else
        {
            /* RX_ONLY Mode */
            txFifo = MCSPI_TX_FIFO_DISABLE;
            if (hwAttrs->rxTrigLvl == 0U)
            {
                rxFifo = MCSPI_RX_FIFO_DISABLE;
                object->fifoSize = 0;
            }
            else
            {
                rxFifo = MCSPI_RX_FIFO_ENABLE;
                object->fifoSize = MCSPI_FULL_FIFO_SIZE;
            }
        }
        McSPITxFIFOConfig(hwAttrs->baseAddr, txFifo, chNum);
        McSPIRxFIFOConfig(hwAttrs->baseAddr, rxFifo, chNum);
    
        if (object->fifoSize > 0U)
        {
            /* FIFO mode is enabled */
    
            /* Set FIFO XFER levels */
            transBytes = (uint32_t)transaction->count << chObj->wordLenShift;
    
            if (transBytes <= object->fifoSize)
            {
                /* Transaction fits entirely in FIFO */
                object->rxTrigLvl = transBytes;
                object->txTrigLvl = transBytes;
            }
            else
            {
                /*
                 * Transaction count is more than FIFO size
                 */
                object->rxTrigLvl = hwAttrs->rxTrigLvl;
                object->txTrigLvl = hwAttrs->txTrigLvl;
    
    #ifdef SPI_DMA_ENABLE
                if (hwAttrs->dmaMode == (bool)true)
                {
                    /*
                     * In DMA mode, update the transaction count to be
                     * multiple of FIFO trigger level size
                     */
                    if (chnCfg->trMode == MCSPI_RX_ONLY_MODE)
                    {
                        transBytes = (transBytes / object->rxTrigLvl) * object->rxTrigLvl;
                    }
                    else
                    {
                        transBytes = (transBytes / object->txTrigLvl) * object->txTrigLvl;
                    }
                    transaction->count = (uint32_t)(transBytes >> chObj->wordLenShift);
                }
                else
    #endif
                {
                    /*
                     * In non-DMA mode, if the RX trigger level equals to the FIFO size,
                     * set the RX trigger level less than the FIFO size, so that TX FIFO
                     * will not under run.
                     */
                    if ((chnCfg->trMode == MCSPI_TX_RX_MODE) &&
                        (object->rxTrigLvl == object->fifoSize))
                    {
                        object->rxTrigLvl -= MCSPI_TX_RX_FIFO_OFFSET;
                    }
                }
            }
            McSPIFIFOTrigLvlSet(hwAttrs->baseAddr, (uint8_t)object->rxTrigLvl,
                                (uint8_t)object->txTrigLvl, chnCfg->trMode);
        }
    
        /* 
         * convert trigger level (in bytes) to word count 
         * based on the word length
         */
        if (object->fifoSize > 0U)
        {
    #ifdef SPI_DMA_ENABLE
            if (hwAttrs->dmaMode == (bool)true)
            {
                wordCount = object->txTrigLvl >> chObj->wordLenShift;
            }
            else
    #endif
            {
                if (transBytes > MCSPI_RX_TX_FIFO_SIZE)
                {
                    wordCount = (uint32_t)MCSPI_RX_TX_FIFO_SIZE >> (chObj->wordLenShift);
                }
                else
                {
                    wordCount = transBytes >> chObj->wordLenShift;
                }
            }
        }
        else
        {
            wordCount = 1U;
        }
        /* Set number of words to be transmitted */
        McSPIWordCountSet(hwAttrs->baseAddr, (uint16_t)transaction->count);
    
        if ((SPI_SLAVE == chObj->spiParams.mode) && (chObj->writeCountIdx != 0U))
        {
    #ifdef SPI_DMA_ENABLE
            if (hwAttrs->dmaMode == (bool)false)
            {
                for (countIndex = 0; countIndex < wordCount; countIndex++)
                {
                    chObj->writeBufIdx = MCSPI_transmitData_v1 (hwAttrs->baseAddr,
                                                                chObj->spiParams.dataSize,
                                                                chObj->writeBufIdx,
                                                                chNum);
                    chObj->writeCountIdx--;
                }
            }
    #else
            for (countIndex = 0; countIndex < wordCount; countIndex++)
            {
                chObj->writeBufIdx = MCSPI_transmitData_v1 (hwAttrs->baseAddr,
                                                            chObj->spiParams.dataSize,
                                                            chObj->writeBufIdx,
                                                            chNum);
                chObj->writeCountIdx--;
            }
    #endif
        }
    }
    
    static bool MCSPI_pollingXferTimeout_v1(uint32_t *timeout, uint32_t *timeoutLoop, uint32_t timeoutVal);
    static bool MCSPI_pollingXferTimeout_v1(uint32_t *timeout, uint32_t *timeoutLoop, uint32_t timeoutVal)
    {
        bool     timeoutFlag = (bool)false;
    
        if (*timeout > 0U)
        {
            *timeout -= 1U;
            if (*timeout == 0U)
            {
                if (*timeoutLoop > 0U)
                {
                    *timeoutLoop -= 1U;
                    *timeout = timeoutVal;
                }
            }
        }
        else
        {
            if (*timeoutLoop == 0U)
            {
                /* Polling transfer timed out */
                timeoutFlag = (bool)true;
            }
        }
    
        return (timeoutFlag);
    }
    
    /*
     *  ======== MCSPI_primeTransfer_v1 ========
     *  This functions configures the transmit and receive channels for a given
     *  MCSPI_Handle and SPI_Transaction.
     *
     *  Slave driver needs to pre-fill the TX trigger level size data to TX FIFO first before
     *  the channel is enabled. If the transfer size is less than the FIFO size (32 bytes), the
     *  TX/RX trigger level is set to the transfer size. If the transfer size is greater than
     *  or equal to the FIFO size, the TX/RX trigger level is set to the FIFO size. The pre-filling
     *  is required to ensure the TX data is available for master to receive when the channel is
     *  enabled.
     *
     *  In polling mode, master driver continuously writes 1 byte TX data to TX FIFO followed
     *  by reading 1 byte RX data from the RX FIFO until all the data are transfered. slave driver
     *  continuously reads 1 byte data from the RX FIFO followed by writing 1 byte TX data to TX
     *  FIFO until all the data are transfered.
     *
     *  In interrupt mode, master driver enables TX empty, RX full and end of word count interrupts.
     *  slave driver enabls RX full interrupt. The TX/RX data are handled in the ISR.
     *
     *  @pre    Function assumes that the handle and transaction is not NULL
     */
    static void MCSPI_primeTransfer_v1(MCSPI_Handle mcHandle, SPI_Transaction *transaction);  /* for misra warnings */
    static void MCSPI_primeTransfer_v1(MCSPI_Handle mcHandle, SPI_Transaction *transaction)
    {
        SPI_Handle            handle;
        SPI_v1_Object        *object;
        SPI_v1_chObject      *chObj;
        uint32_t              chNum;
        SPI_v1_HWAttrs const *hwAttrs;
        SPI_v1_ChnCfg const  *chnCfg;
        uint32_t              channelStatus = 0;
        uint32_t              intStatus;
        uint32_t              timeout;
        uint32_t              timeoutLoop;
        bool                  timeoutFlag;
    
        /* Get the pointer to the object and hwAttrs */
        handle  = mcHandle->handle;
        chNum   = mcHandle->chnNum;
        object = (SPI_v1_Object *)handle->object;
        chObj   = &(object->chObject[chNum]);
        hwAttrs = (const SPI_v1_HWAttrs *)handle->hwAttrs;
        chnCfg  = &(hwAttrs->chnCfg[chNum]);
    
        /* Enable the McSPI channel for communication */
        McSPIChannelEnable(hwAttrs->baseAddr, chNum);
    
        /* setup transfer mode and FIFO trigger levels */
        MCSPI_xferSetup_v1(mcHandle, transaction);
    
        /* Interrupt Mode */
        if(chObj->operMode != (uint32_t)SPI_OPER_MODE_POLLING)
        {
            intStatus =  MCSPI_INT_EOWKE;
            if (chnCfg->trMode == MCSPI_TX_ONLY_MODE)
            {
                intStatus |= (uint32_t)MCSPI_INT_TX_EMPTY(chNum);
            }
            else if (chnCfg->trMode == MCSPI_RX_ONLY_MODE)
            {
                intStatus |= (uint32_t)(MCSPI_INT_RX_FULL(chNum));
            }
            else
            {
                intStatus |= (uint32_t)(MCSPI_INT_RX_FULL(chNum)) | (uint32_t)(MCSPI_INT_TX_EMPTY(chNum));
            }
            McSPIIntStatusClear(hwAttrs->baseAddr, intStatus);
    
            if(SPI_MASTER == chObj->spiParams.mode)
            {
                McSPIIntEnable(hwAttrs->baseAddr, intStatus);
    
                if (hwAttrs->chMode == MCSPI_SINGLE_CH)
                {
                    /* Assert un-used chip select (Force SPIEN) */
                    McSPICSAssert(hwAttrs->baseAddr, chNum);
                }
            }
            else
            {
                McSPIIntEnable(hwAttrs->baseAddr, (uint32_t)(MCSPI_INT_RX_FULL(chNum)));
            }
        }
        /* Polling mode */
        else
        {
            if ((SPI_MASTER == chObj->spiParams.mode) &&
                (hwAttrs->chMode == MCSPI_SINGLE_CH))
            {
                /* SPIEN line is forced to low state.*/
                McSPICSAssert(hwAttrs->baseAddr, chNum);
            }
    
            /* Initialize the timeout value and loop count in polling mode */
            timeout = chObj->spiParams.transferTimeout;
            timeoutLoop = MCSPI_POLLING_TIMEOUT_LOOP;
            timeoutFlag = (bool)false;
    
            /* Polling mode transfer */
            while (((chObj->readCountIdx != 0U) || (chObj->writeCountIdx != 0U)) &&
                   (timeoutFlag == (bool)false))
            {
                channelStatus = McSPIChannelStatusGet(hwAttrs->baseAddr, chNum);
                if ((SPI_MASTER == chObj->spiParams.mode) && (chObj->writeCountIdx != 0U))
                {
                    while (0U == (channelStatus & CSL_MCSPI_CH0STAT_TXS_MASK))
                    {
                        channelStatus = McSPIChannelStatusGet(hwAttrs->baseAddr, chNum);
                        timeoutFlag = MCSPI_pollingXferTimeout_v1(&timeout,
                                                                  &timeoutLoop,
                                                                  chObj->spiParams.transferTimeout);
                        if (timeoutFlag == (bool)true)
                        {
                            break;
                        }
                    }
                    if (timeoutFlag == (bool)false)
                    {
                        chObj->writeBufIdx = MCSPI_transmitData_v1 (hwAttrs->baseAddr,
                                                                    chObj->spiParams.dataSize,
                                                                    chObj->writeBufIdx,
                                                                    chNum);
                        chObj->writeCountIdx--;
                    }
                }
    
                if ((chObj->readCountIdx != 0U) && (timeoutFlag == (bool)false))
                {
                    while (0U == (channelStatus & CSL_MCSPI_CH0STAT_RXS_MASK))
                    {
                        channelStatus = McSPIChannelStatusGet(hwAttrs->baseAddr, chNum);
                        timeoutFlag = MCSPI_pollingXferTimeout_v1(&timeout,
                                                                  &timeoutLoop,
                                                                  chObj->spiParams.transferTimeout);
                        if (timeoutFlag == (bool)true)
                        {
                            printf("MCSPI_pollingXferTimeout_v1 timeout!!!\r\n");  
                            break;
                        }
                    }
                    if (timeoutFlag == (bool)false)
                    {
                        chObj->readBufIdx = MCSPI_receiveData_v1(hwAttrs->baseAddr,
                                                                 chObj->spiParams.dataSize,
                                                                 chObj->readBufIdx,
                                                                 chNum);
                        printf("%02x ", *(uint8_t *)chObj->readBufIdx);                                                                
                        chObj->readCountIdx--;
                    }
                }
                // printf("MCSPI_receiveData_v1 baseAddr 0x%x", hwAttrs->baseAddr);   
                if ((SPI_SLAVE == chObj->spiParams.mode) &&
                    (chObj->writeCountIdx != 0U)         &&
                    (timeoutFlag == (bool)false))
                {
                    chObj->writeBufIdx = MCSPI_transmitData_v1 (hwAttrs->baseAddr,
                                                                chObj->spiParams.dataSize,
                                                                chObj->writeBufIdx,
                                                                chNum);
    
                    chObj->writeCountIdx--;
                }
    
                if ((chObj->readCountIdx != 0U) || (chObj->writeCountIdx != 0U))
                {
                    timeoutFlag = MCSPI_pollingXferTimeout_v1(&timeout,
                                                              &timeoutLoop,
                                                              chObj->spiParams.transferTimeout);
                    if (timeoutFlag == (bool)true)
                    {
                        /* Transfer timeout */
                        transaction->status=SPI_TRANSFER_TIMEOUT;
                    }
                }
                else
                {
                    /* Transfer completed successfully */
                    transaction->status=SPI_TRANSFER_COMPLETED;
                }
            }
    
            if ((SPI_MASTER == chObj->spiParams.mode) &&
                (hwAttrs->chMode == MCSPI_SINGLE_CH))
            {
                /* Force SPIEN line to the inactive state.*/
                McSPICSDeAssert(hwAttrs->baseAddr, chNum);
            }
    
            /* Disable the McSPI channel.*/
            McSPIChannelDisable(hwAttrs->baseAddr, chNum);
    
            chObj->transaction = NULL;
        }
    }
    
    /*
     *  ======== MCSPI_v1_hwiFxn ========
     *  ISR for the MCSPI in master and slave mode
     *
     *  For both TX and RX enabled mode, the following interrupts are enabled:
     *
     *   TX empty interrupt (master only)
     *   RX full interrupt
     *   End of word count interrupt (master only)
     *
     *  When TX empty interrupt happens, ISR will continuously write TX data
     *  to TX FIFO until the FIFO is full or all the TX data is sent out.
     *
     *  When RX full interrupt happens, ISR will continuously read 1 byte
     *  RX data from RX FIFO followed by writing 1 byte TX data to TX FIFO
     *  until the RX FIFO is empty. When all the bytes are transfered or
     *  end of word count interrupt happens (master only), ISR
     *  will disable all the interrupts and call back to the application
     *  in callback mode or release the semaphore in blocking mode.
     *
     *  If the remaining RX count is less than the RX FIFO size,
     *  ISR will set the RX trigger level to the remaing RX count.
     *
     *  To prevent TX FIFO underrun, RX FIFO trigger level is set less
     *  than the max TX FIFO size
     */
    static void MCSPI_v1_hwiFxn (uintptr_t arg); /* for misra warnings */
    static void MCSPI_v1_hwiFxn (uintptr_t arg)
    {
        MCSPI_Handle          mcHandle;
        SPI_Handle            handle;
        SPI_v1_Object        *object;
        SPI_v1_chObject      *chObj;
        uint32_t              chNum;
        SPI_v1_HWAttrs const *hwAttrs;
        SPI_v1_ChnCfg const  *chnCfg;
        uint32_t              intCode = 0;
        bool                  trigLvlChg = (bool)false;
        uint32_t              rdBytes;
        uint32_t              wrBytes;
        uint32_t              chnStatus;
        bool                  loopFlag = (bool)true;
        uint32_t              masterTxCnt = 0;
    
        /* Get the pointer to the object and hwAttrs */
        mcHandle = (MCSPI_Handle)arg;
        handle  = mcHandle->handle;
        chNum   = mcHandle->chnNum;
        object = (SPI_v1_Object *)handle->object;
        chObj   = &(object->chObject[chNum]);
        hwAttrs = (const SPI_v1_HWAttrs *)handle->hwAttrs;
        chnCfg  = &(hwAttrs->chnCfg[chNum]);
    
        intCode = McSPIIntStatusGet(hwAttrs->baseAddr);
    
        while (((chObj->readCountIdx != 0U) || (chObj->writeCountIdx != 0U)) &&
               (loopFlag == (bool)true))
        {
            chnStatus = McSPIChannelStatusGet(hwAttrs->baseAddr, chNum);
            if (SPI_MASTER == chObj->spiParams.mode)
            {
                if (chObj->writeCountIdx != 0U)
                {
                    if (0U == (chnStatus & CSL_MCSPI_CH0STAT_TXFFF_MASK))
                    {
                        /* TX FIFO is not full */
                        chObj->writeBufIdx = MCSPI_transmitData_v1 (hwAttrs->baseAddr,
                                                                    chObj->spiParams.dataSize,
                                                                    chObj->writeBufIdx,
                                                                    chNum);
                        chObj->writeCountIdx--;
                        masterTxCnt++;
                    }
                    else
                    {
                        loopFlag = (bool)false;
                    }
                }
                else
                {
                    loopFlag = (bool)false;
                }
            }
    
            if (chObj->readCountIdx != 0U)
            {
                if ((0U == (chnStatus & CSL_MCSPI_CH0STAT_RXFFE_MASK)) ||
                    (0U != (chnStatus & CSL_MCSPI_CH0STAT_RXS_MASK)))
                {
                    /* RX FIFO is not empty or RX register is full */
                    chObj->readBufIdx = MCSPI_receiveData_v1(hwAttrs->baseAddr,
                                                             chObj->spiParams.dataSize,
                                                             chObj->readBufIdx,
                                                             chNum);
                    chObj->readCountIdx--;
                    loopFlag = (bool)true;
                }
                else
                {
                    if (SPI_MASTER != chObj->spiParams.mode)
                    {
                        loopFlag = (bool)false;
                    }
                }
            }
            else
            {
                if (SPI_MASTER != chObj->spiParams.mode)
                {
                    loopFlag = (bool)false;
                }
            }
    
            if ((SPI_SLAVE == chObj->spiParams.mode) &&
                (chObj->writeCountIdx != 0U))
            {
                if (0U == (chnStatus & CSL_MCSPI_CH0STAT_TXFFF_MASK))
                {
                    /* TX FIFO is not full */
                    chObj->writeBufIdx = MCSPI_transmitData_v1 (hwAttrs->baseAddr,
                                                                chObj->spiParams.dataSize,
                                                                chObj->writeBufIdx,
                                                                chNum);
                    chObj->writeCountIdx--;
                    loopFlag = (bool)true;
                }
            }
            if (masterTxCnt == object->txTrigLvl)
            {
                loopFlag = (bool)false;
            }
        }
    
        /* Update the TX trigger level */
        if (chObj->writeCountIdx != 0U)
        {
            wrBytes = chObj->writeCountIdx << chObj->wordLenShift;
            if (wrBytes < object->txTrigLvl)
            {
                object->txTrigLvl = wrBytes;
                trigLvlChg = (bool)true;
            }
        }
    
        /* Update the RX trigger level */
        if (chObj->readCountIdx > 1U)
        {
            rdBytes = chObj->readCountIdx << chObj->wordLenShift;
            if (rdBytes < object->rxTrigLvl)
            {
                object->rxTrigLvl = rdBytes;
                if (chObj->writeCountIdx == 0U)
                {
                    object->txTrigLvl = object->fifoSize;
                }
                trigLvlChg = (bool)true;
            }
        }
    
        if (trigLvlChg == (bool)true)
        {
            McSPIFIFOTrigLvlSet(hwAttrs->baseAddr, (uint8_t)object->rxTrigLvl,
                                (uint8_t)object->txTrigLvl, chnCfg->trMode);
        }
    
        /*if (MCSPI_INT_EOWKE == (intCode & MCSPI_INT_EOWKE))*/
        if ((MCSPI_INT_EOWKE == (intCode & MCSPI_INT_EOWKE)) ||
            ((chObj->writeCountIdx == 0U) && (chObj->readCountIdx <= 1U) && (chnCfg->trMode != MCSPI_TX_ONLY_MODE)))
        {
            chnStatus = McSPIChannelStatusGet(hwAttrs->baseAddr, chNum);
            while ((0U == (chnStatus & CSL_MCSPI_CH0STAT_EOT_MASK)))
            {
                chnStatus = McSPIChannelStatusGet(hwAttrs->baseAddr, chNum);
            }
            if (chObj->readCountIdx != 0U)
            {
                /* Read final RX byte */
                chObj->readBufIdx = MCSPI_receiveData_v1(hwAttrs->baseAddr,
                                                         chObj->spiParams.dataSize,
                                                         chObj->readBufIdx,
                                                         chNum);
                chObj->readCountIdx--;
            }
            /* Transaction Done */
            intCode = (uint32_t)(MCSPI_INT_RX_FULL(chNum))  |
                      (uint32_t)(MCSPI_INT_TX_EMPTY(chNum)) |
                      MCSPI_INT_EOWKE;
            McSPIIntDisable(hwAttrs->baseAddr,intCode);
            McSPIIntStatusClear(hwAttrs->baseAddr, intCode);
            if ((SPI_MASTER == chObj->spiParams.mode) &&
                (hwAttrs->chMode == MCSPI_SINGLE_CH))
            {
                McSPICSDeAssert(hwAttrs->baseAddr, chNum);
            }
            McSPIChannelDisable(hwAttrs->baseAddr, chNum);
            chObj->transaction->status=SPI_TRANSFER_COMPLETED;
            MCSPI_transferCallback_v1((MCSPI_Handle)arg, chObj->transaction);
        }
    
        McSPIIntStatusClear(hwAttrs->baseAddr, intCode);
    }
    
    /*
     *  ======== MCSPI_init_v1 ========
     *  @pre    Function assumes that the handle is not NULL
     */
    static void MCSPI_init_v1(MCSPI_Handle mcHandle)
    {
        SPI_Handle            handle;
        SPI_v1_Object        *object;
        SPI_v1_chObject      *chObj;
        uint32_t              chNum;
    
        /* Input parameter validation */
        if (mcHandle != NULL)
        {
            /* Get the pointer to the object and hwAttrs */
            handle  = mcHandle->handle;
            chNum   = mcHandle->chnNum;
            object = (SPI_v1_Object*)handle->object;
            chObj   = &(object->chObject[chNum]);
    
            /* reset channel object */
            (void)memset(chObj, 0, sizeof(SPI_v1_chObject));
            chObj->isOpen = (bool)false;
        }
    }
    
    /*
     *  ======== MCSPI_open_v1 ========
     *  @pre    Function assumes that the mcHandle is not NULL
     */
    static MCSPI_Handle MCSPI_open_v1(MCSPI_Handle        mcHandle,
                                      const MCSPI_Params *params)
    {
        SPI_Handle            handle;
        MCSPI_Handle          retMcHandle = mcHandle;
        const MCSPI_Params   *pParams = params;
        SemaphoreP_Params     semParams;
        SPI_v1_Object        *object;
        SPI_v1_chObject      *chObj;
        uint32_t              chNum;
        SPI_v1_HWAttrs const *hwAttrs;
        SPI_v1_ChnCfg const  *chnCfg;
        OsalRegisterIntrParams_t interruptRegParams;
        uint32_t              ret_flag = 0u;
    
        /* Input parameter validation */
        if (mcHandle != NULL)
        {
        /* Get the pointer to the object and hwAttrs */
        handle  = mcHandle->handle;
        chNum   = mcHandle->chnNum;
        object = (SPI_v1_Object *)handle->object;
        chObj   = &(object->chObject[chNum]);
        hwAttrs = (const SPI_v1_HWAttrs *)handle->hwAttrs;
        chnCfg  = &(hwAttrs->chnCfg[chNum]);
    
        /* Determine if the device index was already opened */
        if(chObj->isOpen == (bool)true) {
            retMcHandle = NULL;
        }
        else
        {
            /* Mark the channel handle as being used */
            chObj->isOpen = (bool)true;
    
            /* Store the SPI parameters */
            if (pParams == NULL)
            {
                /* No params passed in, so use the defaults */
                MCSPI_Params_init(&(chObj->spiParams));
                pParams = &(chObj->spiParams);
            }
            else
            {
                chObj->spiParams = *pParams;
            }
    
            if (pParams->dataSize < 4U)
            {
                /* wrong data size param */
                retMcHandle = NULL;
                ret_flag = 1U;
            }
            else if (pParams->dataSize <= 8U)
            {
                chObj->wordLenShift = 0U;
            }
            else if (pParams->dataSize <= 16U)
            {
                chObj->wordLenShift = 1U;
            }
            else if (pParams->dataSize <= 32U)
            {
                chObj->wordLenShift = 2U;
            }
            else
            {
                /* wrong data size param */
                retMcHandle = NULL;
                ret_flag = 1U;
            }
    
            /* Store the current mode. Extract operating mode from hwAttrs and params */
            if(SPI_MODE_BLOCKING == pParams->transferMode)
            {
                if ((bool)true == hwAttrs->enableIntr)
                {
                    chObj->operMode = (uint32_t)SPI_OPER_MODE_BLOCKING;
                }
    #ifdef SPI_DMA_ENABLE
                else if ((bool)true == hwAttrs->dmaMode)
                {
                    chObj->operMode = (uint32_t)SPI_OPER_MODE_BLOCKING;
                }
    #endif
                else
                {
                    chObj->operMode = (uint32_t)SPI_OPER_MODE_POLLING;
                }
            }
            else
            {
                chObj->operMode = (uint32_t)SPI_OPER_MODE_CALLBACK;
                /* Check to see if a callback function was defined for async mode */
                if ((pParams->transferCallbackFxn == NULL) &&
                    (object->transferCallbackFxn == NULL))
                {
                    retMcHandle = NULL;
                    ret_flag = 1U;
                }
            }
    
            if ((chObj->operMode != (uint32_t)SPI_OPER_MODE_POLLING) &&
                (object->hwi == NULL))
            {
                /* register interrrupt when the 1st
                   channel of the instance is opened */
                Osal_RegisterInterrupt_initParams(&interruptRegParams);             
    
                interruptRegParams.corepacConfig.name=NULL;
    #ifdef __TI_ARM_V7R4__
                interruptRegParams.corepacConfig.priority=0x8U;
    #else
                interruptRegParams.corepacConfig.priority=0x20U;
    #endif
                interruptRegParams.corepacConfig.corepacEventNum = (int32_t)hwAttrs->eventId;
                interruptRegParams.corepacConfig.intVecNum = (int32_t)hwAttrs->intNum; /* Host Interrupt vector */
                interruptRegParams.corepacConfig.isrRoutine  = (void (*)(uintptr_t))(&MCSPI_v1_hwiFxn);
                interruptRegParams.corepacConfig.arg         = (uintptr_t)mcHandle;
    
                (void)SPI_osalRegisterInterrupt(&interruptRegParams,&(object->hwi));
    
                if(object->hwi == NULL)
                {
                    MCSPI_close_v1(mcHandle);
                    ret_flag = 1u;
                    retMcHandle = NULL;
                }
            }
    
            if(ret_flag == 0u)
            {
                /*
                 * Construct thread safe handles for this SPI peripheral
                 * Semaphore to provide exclusive access to the SPI peripheral
                 */
                if (object->mutex == NULL)
                {
                    SPI_osalSemParamsInit(&semParams);
                    semParams.mode = SemaphoreP_Mode_BINARY;
                    object->mutex = SPI_osalCreateBlockingLock(1U, &semParams);
                }
    
                if (chObj->operMode == (uint32_t)SPI_OPER_MODE_BLOCKING)
                {
                    /*
                     * Construct a semaphore to block task execution for the duration of the
                     * SPI transfer
                     */
                    if (object->transferComplete == NULL)
                    {
                        SPI_osalSemParamsInit(&semParams);
                        semParams.mode = SemaphoreP_Mode_BINARY;
                        object->transferComplete = SPI_osalCreateBlockingLock(0U, &semParams);
                    }
                }
    
                chObj->transaction = NULL;
    
                /* Extract clock mode from the frame format */
                switch(pParams->frameFormat)
                {
                    case SPI_POL0_PHA0:
                        chObj->clockMode = MCSPI_CLK_MODE_0;
                        break;
    
                    case SPI_POL0_PHA1:
                        chObj->clockMode = MCSPI_CLK_MODE_1;
                        break;
    
                    case SPI_POL1_PHA0:
                        chObj->clockMode = MCSPI_CLK_MODE_2;
                        break;
    
                    case SPI_POL1_PHA1:
                        chObj->clockMode = MCSPI_CLK_MODE_3;
                        break;
    
                    default:
                    	chObj->clockMode = MCSPI_CLK_MODE_2;
                        break;
                }
    
                if (object->chOpenedCnt == 0U)
                {
    #ifdef SPI_DMA_ENABLE
                    if (hwAttrs->dmaMode == (bool)true)
                    {
                        /* DMA Configuration */
                        (void)MCSPI_dmaConfig(mcHandle);
    
                        McSPIDMADisable(hwAttrs->baseAddr,
                                        ((uint32_t) MCSPI_DMA_RX_EVENT | (uint32_t) MCSPI_DMA_TX_EVENT),
                                        chNum);
                    }
    #endif
                    /* Reset SPI Peripheral */
                    McSPIReset(hwAttrs->baseAddr);
    
                    MCSPISysConfigSetup(hwAttrs->baseAddr, MCSPI_CLOCKS_OCP_ON_FUNC_ON,
                                        MCSPI_SIDLEMODE_NO, MCSPI_WAKEUP_DISABLE,
                                        MCSPI_AUTOIDLE_OFF);
    
                    if (hwAttrs->chMode == MCSPI_SINGLE_CH)
                    {
                        /* Configure 3 pin or 4 pin mode */
                        if((uint32_t)SPI_PINMODE_3_PIN == hwAttrs->pinMode)
                        {
                            /* Disable chip select pin.*/
                            McSPICSDisable(hwAttrs->baseAddr);
                        }
                        else
                        {
                            /* Enable chip select pin.*/
                            McSPICSEnable(hwAttrs->baseAddr);
                        }
                    }
                }
    
                if ((object->chOpenedCnt != 0U) &&
                    ((pParams->mode != SPI_MASTER) || (object->mode != SPI_MASTER)))
                {
    
                    /*
                     * McSPI supports multiple master channels or single slave channel per instance:
                     *
                     * 1. if an instance has already had a channle opened in SPI_MASTER mode,
                     * the new channel being opened should have the same SPI mode as the previous
                     * channel opened.
                     *
                     * 2. if an instance has already had a channle opened in SPI_SLAVE mode,
                     * no new channel can be opened.
                     */
                    ret_flag = 1u;
                    retMcHandle = NULL;
                }
    
                if((SPI_MASTER == pParams->mode) && (ret_flag == 0U))
                {
                    if (object->chOpenedCnt == 0U)
                    {
                        /*
                         * first channel opened in this instance,
                         * enable SPI Master
                         */
                        McSPIMasterModeEnable(hwAttrs->baseAddr);
                        object->mode = SPI_MASTER;
                    }
    
                    /* Configure the peripheral as single channel SPI Master */
                    (void)McSPIMasterModeConfig(hwAttrs->baseAddr,
                                                hwAttrs->chMode,
                                                chnCfg->trMode,
                                                chnCfg->dataLineCommMode,
                                                chNum);
                    /* Clock configuration */
                    McSPIClkConfig(hwAttrs->baseAddr,
                                   hwAttrs->inputClkFreq,
                                   pParams->bitRate,
                                   chNum,
                                   chObj->clockMode);
    
                    /* configure initial SPI delay only in signle master mode */
                    if ((hwAttrs->chMode == MCSPI_SINGLE_CH) && (object->chOpenedCnt == 0U))
                    {
                        McSPIInitDelayConfig(hwAttrs->baseAddr, hwAttrs->initDelay);
                    }
                }
                else
                {
                    if (object->chOpenedCnt == 0U)
                    {
                        /*
                         * first channel opened in this instance,
                         * enable SPI Slave
                         */
                        McSPISlaveModeEnable(hwAttrs->baseAddr);
                        object->mode = SPI_SLAVE;
                    }
    
                    /* Clock configuration */
                    McSPIClkConfig(hwAttrs->baseAddr,
                                   hwAttrs->inputClkFreq,
                                   pParams->bitRate,
                                   chNum,
                                   chObj->clockMode);
    
                    /* Set pin direction. */
                    (void)MCSPIPinDirSet(hwAttrs->baseAddr,
                                         chnCfg->trMode,
                                         chnCfg->dataLineCommMode,
                                         chNum);
                }
    
                /* Set word length for corresponding channel */
                McSPIWordLengthSet(hwAttrs->baseAddr,
                                   MCSPI_WORD_LENGTH(pParams->dataSize),
                                   chNum);
    
                /* Set polarity of SPIEN to low.*/
                McSPICSPolarityConfig(hwAttrs->baseAddr,
                                      chnCfg->csPolarity,
                                      chNum);
            }
    
            if(SPI_MASTER == pParams->mode)
            {
                /* Configure chip-select time control */
                McSPICSTimeControlSet(hwAttrs->baseAddr, chnCfg->tcs, chNum);
            }
    
            /* increment the channel opened count */
            object->chOpenedCnt++;
        }
        }
    
        return (retMcHandle);
    }
    
    /*
     *  ======== MCSPI_transfer_v1 ========
     *  @pre    Function assumes that mcHandle and transaction is not NULL
     */
    static bool MCSPI_transfer_v1(MCSPI_Handle mcHandle, SPI_Transaction *transaction)
    {
        SPI_Handle            handle;
        SPI_v1_Object        *object;
        SPI_v1_chObject      *chObj;
        SPI_v1_HWAttrs const *hwAttrs;
        uint32_t              chNum, clrInt = 0U;;
        bool                  ret_val = (bool)false;
        SemaphoreP_Status   semStatus = SemaphoreP_OK;
    
        /* Input parameter validation */
        if ((mcHandle != NULL) && (transaction != NULL))
        {
        /* Get the pointer to the object and hwAttrs */
        handle  = mcHandle->handle;
        chNum   = mcHandle->chnNum;
        object = (SPI_v1_Object *)handle->object;
        chObj   = &(object->chObject[chNum]);
        hwAttrs = (const SPI_v1_HWAttrs *)handle->hwAttrs;
    
        /* Acquire the lock for the SPI transfer on this instance */
        (void)SPI_osalPendLock(object->mutex, SemaphoreP_WAIT_FOREVER);
        if (chObj->spiParams.transferTimeout == 0U)
        {
            /* timeout cannot be NO_WAIT, set it to default value */
            chObj->spiParams.transferTimeout = SPI_WAIT_FOREVER;
        }
    
        if ((uint32_t)transaction->count != 0U)
        {
            transaction->status = SPI_TRANSFER_STARTED;
    
            /* Check if a transfer is in progress */
            if (chObj->transaction != NULL)
            {
                transaction->status = SPI_TRANSFER_CANCELED;
    
                /* transfer is in progress */
                ret_val = (bool)false;
            }
            else
            {
                /* Save the pointer to the transaction */
                chObj->transaction = transaction;
    
    #ifdef SPI_DMA_ENABLE
                if (hwAttrs->dmaMode == (bool)true)
                {
                    MCSPI_dmaTransfer(mcHandle, transaction);
                }
                else
    #endif
                {
                    MCSPI_primeTransfer_v1(mcHandle, transaction);
                }
    
                if (chObj->operMode == (uint32_t)SPI_OPER_MODE_BLOCKING)
                {
                    semStatus = SPI_osalPendLock(object->transferComplete, chObj->spiParams.transferTimeout);
                }
                if (semStatus == SemaphoreP_TIMEOUT)
                {
                    /* clear the interrupts */
                    clrInt = (uint32_t)((MCSPI_INT_TX_EMPTY(chNum) | MCSPI_INT_RX_FULL(chNum)
                                        | MCSPI_INT_EOWKE));
                    if(SPI_MASTER == chObj->spiParams.mode)
                    {
                        McSPIIntDisable(hwAttrs->baseAddr, clrInt);
                    }
                    else
                    {
                        McSPIIntDisable(hwAttrs->baseAddr, (uint32_t)(MCSPI_INT_RX_FULL(chNum)));
                    }
                    McSPIIntStatusClear(hwAttrs->baseAddr, clrInt);
                    if ((SPI_MASTER == chObj->spiParams.mode) &&
                        (hwAttrs->chMode == MCSPI_SINGLE_CH))
                    {
                        McSPICSDeAssert(hwAttrs->baseAddr, chNum);
                    }
                    McSPIChannelDisable(hwAttrs->baseAddr, chNum);
    
                    /*
                     * Interrupt/dma (timeout) transaction
                     * returns timeout status
                     */
                    transaction->status=SPI_TRANSFER_TIMEOUT;
                    chObj->transaction = NULL;
                    ret_val = (bool)false;
                }
                else
                {
                    if (chObj->operMode == (uint32_t)SPI_OPER_MODE_POLLING)
                    {
                        /*
                         * Polling transaction status is set in MCSPI_primeTransfer_v1
                         */
                        if (transaction->status == SPI_TRANSFER_COMPLETED)
                        {
                            ret_val = (bool)true;
                        }
                        else
                        {
                            ret_val = (bool)false;
                        }
                    }
                    else
                    {
                        /*
                         * Callback transaction or interrupt/dma (no timeout) transaction
                         * returns completed status
                         */
                        transaction->status = SPI_TRANSFER_COMPLETED;
                        ret_val = (bool)true;
                    }
                }
            }
        }
        else
        {
            transaction->status=SPI_TRANSFER_CANCELED;
        }
    
        /* Release the lock for the SPI transfer on this instance */
        (void)SPI_osalPostLock(object->mutex);
        }
    
        return (ret_val);
    }
    
    /*
     *  ======== MCSPI_transferCallback_v1 ========
     *  Callback function for when the SPI is in SPI_MODE_BLOCKING
     *
     *  @pre    Function assumes that the handle is not NULL
     */
    void MCSPI_transferCallback_v1(MCSPI_Handle     mcHandle,
                                   SPI_Transaction *transaction)
    {
        SPI_Handle         handle;
        SPI_v1_Object     *object;
        SPI_v1_chObject   *chObj;
        uint32_t           chNum;
    
        if (mcHandle != NULL)
        {
        /* Get the pointer to the channel object */
        handle  = mcHandle->handle;
        chNum   = mcHandle->chnNum;
        object = (SPI_v1_Object*)handle->object;
        chObj   = &(object->chObject[chNum]);
    
        if (chObj->operMode == (uint32_t)SPI_OPER_MODE_CALLBACK)
        {
            if (object->transferCallbackFxn != NULL)
            {
                /* Single channel mode callback */
                object->transferCallbackFxn(handle, transaction);
            }
            else
            {
                /* multi channel mode callback */
                chObj->spiParams.transferCallbackFxn(mcHandle, transaction);
            }
        }
        else
        {
            (void)SPI_osalPostLock(object->transferComplete);
        }
    
        chObj->transaction = NULL;
        }
    }
    
    /*
     *  ======== MCSPI_transferCancel_v1 ========
     */
    static void MCSPI_transferCancel_v1(MCSPI_Handle mcHandle)
    {
        SPI_Handle            handle;
        SPI_v1_Object        *object;
        SPI_v1_chObject      *chObj;
        SPI_v1_HWAttrs const *hwAttrs;
        uint32_t              chNum;
        uint32_t              intCode;
    
        /* Get the pointer to the channel object */
        handle  = mcHandle->handle;
        chNum   = mcHandle->chnNum;
        object  = (SPI_v1_Object*)handle->object;
        chObj   = &(object->chObject[chNum]);
        hwAttrs = (const SPI_v1_HWAttrs *)handle->hwAttrs;
    
        if(true == hwAttrs->enableIntr)
        {
            intCode = (uint32_t)(MCSPI_INT_RX_FULL(chNum))  |
                      (uint32_t)(MCSPI_INT_TX_EMPTY(chNum)) |
                      MCSPI_INT_EOWKE;
            McSPIIntDisable(hwAttrs->baseAddr,intCode);
            McSPIIntStatusClear(hwAttrs->baseAddr, intCode);
        }
    
        if ((SPI_MASTER == chObj->spiParams.mode) &&
            (hwAttrs->chMode == MCSPI_SINGLE_CH))
        {
            McSPICSDeAssert(hwAttrs->baseAddr, chNum);
        }
        McSPIChannelDisable(hwAttrs->baseAddr, chNum);
    
        chObj->transaction->status = SPI_TRANSFER_CANCELED;
        MCSPI_transferCallback_v1(mcHandle, chObj->transaction);
    
        return;
    }
    
    /*
     *  ======== MCSPI_control_v1 ========
     */
    static int32_t MCSPI_control_v1(MCSPI_Handle mcHandle, uint32_t cmd, const void *arg)
    {
        (void)mcHandle;
        (void)cmd;
        arg = arg;
        return SPI_STATUS_UNDEFINEDCMD;
    }
    
    /**
     *  \brief  function is used to clear the channel specific interrupt status
     */
    void MCSPI_clearIntStatus(MCSPI_Handle mcHandle)
    {
        SPI_Handle            handle;
        SPI_v1_HWAttrs const *hwAttrs;
        uint32_t              chNum;
        uint32_t              clrIntr = (uint32_t) 0;
    
        /* Get the pointer to the hwAttrs */
        handle  = mcHandle->handle;
        chNum   = mcHandle->chnNum;
        hwAttrs = (const SPI_v1_HWAttrs *)handle->hwAttrs;
    
        switch (chNum)
        {
            case MCSPI_CHANNEL_0:
                    /* clear all channel '0' interrupts */
                    clrIntr = (uint32_t) 0;
    
                    clrIntr = (CSL_MCSPI_IRQSTATUS_TX0_EMPTY_MASK |
                                   CSL_MCSPI_IRQSTATUS_TX0_UNDERFLOW_MASK |
                                   CSL_MCSPI_IRQSTATUS_RX0_FULL_MASK);
    
                    McSPIIntStatusClear((uint32_t) hwAttrs->baseAddr, clrIntr);
    
                break;
    
            case MCSPI_CHANNEL_1:
                    /* Enable all channel '1' interrupts */
                    clrIntr = (uint32_t) 0;
                    clrIntr = (CSL_MCSPI_IRQSTATUS_TX1_EMPTY_MASK |
                               CSL_MCSPI_IRQSTATUS_TX1_UNDERFLOW_MASK |
                               CSL_MCSPI_IRQSTATUS_RX1_FULL_MASK);
    
                    McSPIIntStatusClear((uint32_t) hwAttrs->baseAddr, clrIntr);
    
                break;
    
            case MCSPI_CHANNEL_2:
                    /* Enable all channel '2' interrupts */
                    clrIntr = (uint32_t) 0;
                    clrIntr = (CSL_MCSPI_IRQSTATUS_TX2_EMPTY_MASK |
                               CSL_MCSPI_IRQSTATUS_TX2_UNDERFLOW_MASK |
                               CSL_MCSPI_IRQSTATUS_RX2_FULL_MASK);
    
                    McSPIIntStatusClear((uint32_t) hwAttrs->baseAddr, clrIntr);
    
                break;
    
            case MCSPI_CHANNEL_3:
                    /* Enable all channel '3' interrupts */
                    clrIntr = (uint32_t) 0;
                    clrIntr = (CSL_MCSPI_IRQSTATUS_TX3_EMPTY_MASK |
                               CSL_MCSPI_IRQSTATUS_TX3_UNDERFLOW_MASK |
                               CSL_MCSPI_IRQSTATUS_RX3_FULL_MASK);
    
                    McSPIIntStatusClear((uint32_t) hwAttrs->baseAddr, clrIntr);
    
                break;
    
            default:
                break;
        }
    }
    
    /**
     *  \brief  function is used to clear the channel specific interrupt error status
     */
    void MCSPI_clearIntErrStatus(MCSPI_Handle mcHandle, uint32_t intStatus)
    {
        SPI_Handle            handle;
        uint32_t              chNum;
        SPI_v1_HWAttrs const *hwAttrs;
    
        /* Get the pointer to the hwAttrs */
        handle  = mcHandle->handle;
        chNum   = mcHandle->chnNum;
        hwAttrs = (const SPI_v1_HWAttrs *)handle->hwAttrs;
    
        /* check Timeout interrupt                                           */
        switch (chNum)
        {
            case MCSPI_CHANNEL_0:
    
                if ((uint32_t) CSL_MCSPI_IRQSTATUS_TX0_UNDERFLOW_MASK ==
                    (intStatus & (uint32_t) CSL_MCSPI_IRQSTATUS_TX0_UNDERFLOW_MASK))
                {
                    McSPIIntStatusClear(
                        (uint32_t) hwAttrs->baseAddr,
                        (uint32_t) CSL_MCSPI_IRQSTATUS_TX0_UNDERFLOW_MASK);
                }
                break;
    
            case MCSPI_CHANNEL_1:
    
                if ((uint32_t) CSL_MCSPI_IRQSTATUS_TX1_UNDERFLOW_MASK ==
                    (intStatus & (uint32_t) CSL_MCSPI_IRQSTATUS_TX1_UNDERFLOW_MASK))
                {
                    McSPIIntStatusClear(
                        (uint32_t) hwAttrs->baseAddr,
                        (uint32_t) CSL_MCSPI_IRQSTATUS_TX1_UNDERFLOW_MASK);
                }
                break;
    
            case MCSPI_CHANNEL_2:
                if ((uint32_t) CSL_MCSPI_IRQSTATUS_TX2_UNDERFLOW_MASK ==
                    (intStatus & (uint32_t) CSL_MCSPI_IRQSTATUS_TX2_UNDERFLOW_MASK))
                {
                    McSPIIntStatusClear(
                        (uint32_t) hwAttrs->baseAddr,
                        (uint32_t) CSL_MCSPI_IRQSTATUS_TX2_UNDERFLOW_MASK);
                }
                break;
    
            case MCSPI_CHANNEL_3:
    
                if ((uint32_t) CSL_MCSPI_IRQSTATUS_TX3_UNDERFLOW_MASK ==
                    (intStatus & (uint32_t) CSL_MCSPI_IRQSTATUS_TX3_UNDERFLOW_MASK))
                {
                    McSPIIntStatusClear(
                        (uint32_t) hwAttrs->baseAddr,
                        (uint32_t) CSL_MCSPI_IRQSTATUS_TX3_UNDERFLOW_MASK);
                }
                break;
    
            default:
                break;
        }
    }
    

    and the file /home/huangjiasheng/ti-processor-sdk-rtos-j721e-evm-07_01_00_11/pdk_jacinto_07_01_00_45/packages/ti/drv/spi/src/SPI_drv.c

    /**
     *  \file   SPI_drv.c
     *
     *  \brief  SPI Driver high level APIs.
     *
     *   This file contains the driver APIs for SPI.
     */
    
    /*
     * Copyright (C) 2014-2017 Texas Instruments Incorporated - http://www.ti.com/
     *
     * 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.
     *
     */
    
    #include <ti/drv/spi/MCSPI.h>
    #include <stdint.h>
    #include <stdlib.h>
    #include <ti/drv/spi/src/SPI_osal.h>
    
    
    /* Externs */
    extern const SPI_config_list SPI_config;
    extern MCSPI_config_list MCSPI_config;
    
    /* Used to check status and initialization */
    static int32_t SPI_count = (-((int32_t)1));
    
    static void   *spiMutex = NULL;
    
    /* Default SPI parameters structure */
    const SPI_Params SPI_defaultParams = {
        SPI_MODE_BLOCKING,  /* transferMode */
        0U,                 /* transferTimeout */
        NULL,               /* transferCallbackFxn */
        SPI_MASTER,         /* mode */
        1000000,            /* bitRate */
        8,                  /* dataSize */
        SPI_POL0_PHA0,      /* frameFormat */
        NULL                /* custom */
    };
    
    /* Default MCSPI parameters structure */
    const MCSPI_Params MCSPI_defaultParams = {
        SPI_MODE_BLOCKING,  /* transferMode */
        0U,                 /* transferTimeout */
        NULL,               /* transferCallbackFxn */
        SPI_MASTER,         /* mode */
        1000000,            /* bitRate */
        8,                  /* dataSize */
        SPI_POL0_PHA0,      /* frameFormat */
        NULL                /* custom */
    };
    
    /*
     *  ======== SPI_close ========
     */
    void SPI_close(SPI_Handle handle)
    {
        if (handle != NULL)
        {
            if (spiMutex != NULL)
            {
                /* Acquire the the SPI driver semaphore */
                (void)SPI_osalPendLock(spiMutex, SemaphoreP_WAIT_FOREVER);
            }
    
            handle->fxnTablePtr->closeFxn(handle);
    
            if (spiMutex != NULL)
            {
                /* Release the the SPI driver semaphorel */
                (void)SPI_osalPostLock(spiMutex);
            }
        }
    }
    
    /*
     *  ======== SPI_control ========
     */
    int32_t SPI_control(SPI_Handle handle, uint32_t cmd, void *arg)
    {
        int32_t retVal = SPI_STATUS_ERROR;
    
        if (handle != NULL)
        {
            retVal = handle->fxnTablePtr->controlFxn(handle, cmd, arg);
        }
    
        return (retVal);
    }
    
    /*
     *  ======== SPI_init ========
     */
    void SPI_init(void)
    {
        SemaphoreP_Params     semParams;
    
        if (SPI_count == (-((int32_t)1))) {
            /* Call each driver's init function */
            for (SPI_count = 0; (SPI_count < (int32_t)SPI_MAX_CONFIG_CNT) && (SPI_config[SPI_count].fxnTablePtr != NULL); SPI_count++) {
                SPI_config[SPI_count].fxnTablePtr->spiInitFxn((SPI_Handle)&(SPI_config[SPI_count]));
            }
        }
    
        /*
         * Construct thread safe handles for SPI driver level
         * Semaphore to provide exclusive access to the SPI APIs
         */
        if (spiMutex == NULL)
        {
            SPI_osalSemParamsInit(&semParams);
            semParams.mode = SemaphoreP_Mode_BINARY;
            spiMutex = SPI_osalCreateBlockingLock(1U, &semParams);
        }
    }
    
    /*
     *  ======== SPI_open ========
     */
    SPI_Handle SPI_open(uint32_t index, SPI_Params *params)
    {
        SPI_Handle handle = NULL;
    
        if ((SPI_Handle)&(SPI_config[index]) != NULL)
        {
            /* Get handle for this driver instance */
            handle = (SPI_Handle)&(SPI_config[index]);
    
            if (spiMutex != NULL)
            {
                /* Acquire the the SPI driver semaphore */
                (void)SPI_osalPendLock(spiMutex, SemaphoreP_WAIT_FOREVER);
            }
    
            handle = handle->fxnTablePtr->openFxn(handle, params);
    
            if (spiMutex != NULL)
            {
                /* Release the the SPI driver semaphorel */
                (void)SPI_osalPostLock(spiMutex);
            }
        }
    
        return (handle);
    }
    
    /*
     *  ======== SPI_Params_init ========
     */
    void SPI_Params_init(SPI_Params *params)
    {
        if (params != NULL)
        {
            *params = SPI_defaultParams;
        }
    }
    
    /*
     *  ======== SPI_serviceISR ========
     */
    void SPI_serviceISR(SPI_Handle handle)
    {
        if (handle != NULL)
        {
            handle->fxnTablePtr->serviceISRFxn(handle);
        }
    }
    
    /*
     *  ======== SPI_transfer ========
     */
    bool SPI_transfer(SPI_Handle handle, SPI_Transaction *transaction)
    {
        bool retVal = (bool)false;
    
        if ((handle != NULL) && (transaction != NULL))
        {
            retVal = handle->fxnTablePtr->transferFxn(handle, transaction);
        }
    
        return (retVal);
    }
    
    /*
     *  ======== SPI_transferCancel ========
     */
    void SPI_transferCancel(SPI_Handle handle)
    {
        if (handle != NULL)
        {
            handle->fxnTablePtr->transferCancelFxn(handle);
        }
    }
    
    /*
     *  ======== MCSPI_close ========
     */
    void MCSPI_close(MCSPI_Handle handle)
    {
        if (handle != NULL)
        {
            if (spiMutex != NULL)
            {
                /* Acquire the the SPI driver semaphore */
                (void)SPI_osalPendLock(spiMutex, SemaphoreP_WAIT_FOREVER);
            }
    
            handle->fxnTablePtr->closeFxn(handle);
    
            if (spiMutex != NULL)
            {
                /* Release the the SPI driver semaphorel */
                (void)SPI_osalPostLock(spiMutex);
            }
        }
    }
    
    /*
     *  ======== MCSPI_control ========
     */
    int32_t MCSPI_control(MCSPI_Handle handle, uint32_t cmd, void *arg)
    {
        int32_t retVal = SPI_STATUS_ERROR;
    
        if (handle != NULL)
        {
            retVal = handle->fxnTablePtr->controlFxn(handle, cmd, arg);
        }
    
        return (retVal);
    }
    
    /*
     *  ======== MCSPI_init ========
     */
    void MCSPI_init(void)
    {
        SPI_init();
    }
    
    /*
     *  ======== MCSPI_open ========
     */
    MCSPI_Handle MCSPI_open(uint32_t index, uint32_t channel, MCSPI_Params *params)
    {
        MCSPI_Handle handle = NULL;
    
        if ((MCSPI_Handle)&(MCSPI_config[index][channel]) != NULL)
        {
            /* Get handle for this driver instance */
            handle = (MCSPI_Handle)&(MCSPI_config[index][channel]);
    
            if (spiMutex != NULL)
            {
                /* Acquire the the SPI driver semaphore */
                (void)SPI_osalPendLock(spiMutex, SemaphoreP_WAIT_FOREVER);
            }
    
            handle = handle->fxnTablePtr->openFxn(handle, params);
    
            if (spiMutex != NULL)
            {
                /* Release the the SPI driver semaphorel */
                (void)SPI_osalPostLock(spiMutex);
            }
        }
    
        return (handle);
    }
    
    /*
     *  ======== MCSPI_Params_init ========
     */
    void MCSPI_Params_init(MCSPI_Params *params)
    {
        if (params != NULL)
        {
            *params = MCSPI_defaultParams;
        }
    }
    
    /*
     *  ======== _transfer ========
     */
    bool MCSPI_transfer(MCSPI_Handle handle, SPI_Transaction *transaction)
    {
        bool retVal = (bool)false;
    
        if ((handle != NULL) && (transaction != NULL))
        {
            retVal = handle->fxnTablePtr->transferFxn(handle, transaction);
        }
    
        return (retVal);
    }
    
    /*
     *  ======== _transferCancel ========
     */
    void MCSPI_transferCancel(MCSPI_Handle handle)
    {
        if (handle != NULL)
        {
            handle->fxnTablePtr->transferCancelFxn(handle);
        }
    }
    

     and the openvx of spi rx is the file ~/ti-processor-sdk-rtos-j721e-evm-07_01_00_11/vision_apps/kernels/pdd_kernel/r5f/vx_spirx_target.c, which we refer to file ~/ti-processor-sdk-rtos-j721e-evm-07_01_00_11/vision_apps/kernels/sample/r5f/vx_pcie_rx_target.c

    /*
     *
     * Copyright (c) 2018 Texas Instruments Incorporated
     *
     * All rights reserved not granted herein.
     *
     * Limited License.
     *
     * Texas Instruments Incorporated grants a world-wide, royalty-free, non-exclusive
     * license under copyrights and patents it now or hereafter owns or controls to make,
     * have made, use, import, offer to sell and sell ("Utilize") this software subject to the
     * terms herein.  With respect to the foregoing patent license, such license is granted
     * solely to the extent that any such patent is necessary to Utilize the software alone.
     * The patent license shall not apply to any combinations which include this software,
     * other than combinations with devices manufactured by or for TI ("TI Devices").
     * No hardware patent is licensed hereunder.
     *
     * Redistributions must preserve existing copyright notices and reproduce this license
     * (including the above copyright notice and the disclaimer and (if applicable) source
     * code license limitations below) in the documentation and/or other materials provided
     * with the distribution
     *
     * Redistribution and use in binary form, without modification, are permitted provided
     * that the following conditions are met:
     *
     * *       No reverse engineering, decompilation, or disassembly of this software is
     * permitted with respect to any software provided in binary form.
     *
     * *       any redistribution and use are licensed by TI for use only with TI Devices.
     *
     * *       Nothing shall obligate TI to provide you with source code for the software
     * licensed and provided to you in object code.
     *
     * If software source code is provided to you, modification and redistribution of the
     * source code are permitted provided that the following conditions are met:
     *
     * *       any redistribution and use of the source code, including any resulting derivative
     * works, are licensed by TI for use only with TI Devices.
     *
     * *       any redistribution and use of any object code compiled from the source code
     * and any resulting derivative works, are licensed by TI for use only with TI Devices.
     *
     * Neither the name of Texas Instruments Incorporated nor the names of its suppliers
     *
     * may be used to endorse or promote products derived from this software without
     * specific prior written permission.
     *
     * DISCLAIMER.
     *
     * THIS SOFTWARE IS PROVIDED BY TI AND TI'S LICENSORS "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 TI AND TI'S LICENSORS 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.
     *
     */
    /* ========================================================================== */
    /*                             Include Files                                  */
    /* ========================================================================== */
    #include <stdio.h>
    // // #include <ti/csl/csl_mcspi.h>
    // #include <ti/csl/soc.h>
    // #include <ti/drv/uart/UART_stdio.h>
    #include <ti/drv/spi/SPI.h>
    #include <ti/board/board.h>
    #include <ti/csl/src/ip/mcspi/V0/mcspi.h>
    #include <ti/osal/RegisterIntr.h>
    #include <ti/drv/spi/src/SPI_osal.h>
    #include "TI/tivx_yh_pdd.h"
    
    #include <TI/tivx_task.h>
    #include "TI/tivx.h"
    #include "TI/j7.h"
    #include "TI/tivx_yh_pdd_spi.h"
    #include <TI/tivx_yh_pdd.h>
    #include "TI/tivx_event.h"
    #include <ti/sysbios/knl/Event.h>
    #include <ti/sysbios/BIOS.h>
    
    #include "TI/tivx_target_kernel.h"
    #include "tivx_kernel_spirx.h"
    
    #include <ti/csl/soc/j721e/src/cslr_intr_r5fss0_core0.h>
    #include <ti/csl/soc/j721e/src/cslr_intr_r5fss0_core1.h>
    #include <ti/csl/soc/j721e/src/cslr_intr_r5fss1_core0.h>
    #include <ti/csl/soc/j721e/src/cslr_intr_r5fss1_core1.h>
    #include <ti/csl/soc/j721e/src/cslr_intr_r5fss0_introuter0.h>
    
    
    #include <ti/drv/spi/SPI.h>
    #include <ti/drv/spi/soc/SPI_v1.h>
    
    #include <ti/drv/spi/soc/SPI_soc.h>
    #include <ti/drv/spi/src/SPI_osal.h>
    #include <ti/drv/spi/SPI.h>
    #include <ti/drv/spi/MCSPI.h>
    
    Event_Handle        gSpirxIntrEvent;
    Event_Struct        gSpirxIntrEventMem;
    
    
    
    /* ========================================================================== */
    /*                                 Macros                                     */
    /* ========================================================================== */
    #define MCSPIRX_IN_CLK                (48000000U)
    #define MCSPIRX_OUT_CLK               (10000000U)
    #define McSPIRX_DATA_COUNT            (128)//(256U)
    #define CSL_MCSPI0_CFG_BASE (0x2100000UL)
    #define CSL_MCSPI1_CFG_BASE (0x2110000UL)
    #define CSL_MCSPI2_CFG_BASE (0x2120000UL)
    #define BUFFER_RECV_COUNT 10
    
    /** \brief MCSPI Channel number*/
    #define MCSPI_CH_NUM                (0U)
    /* ========================================================================== */
    /*                           when use interrupt used                         */
    /* ========================================================================== */
    
    /* ========================================================================== */
    /*       when use spi2 used,tda4A for master, tda4B for slave                 */
    /* ========================================================================== */
    
    #define gMcSpi_tda4AMaster_to_tda4BSlave
    
    /* ========================================================================== */
    /*                    use when using spirx node alone                        */
    /* ========================================================================== */
    
    /* ========================================================================== */
    /*                            Global Variables                                */
    /* ========================================================================== */
    uint32_t          gChNum_rx  = 0U;
    uint8_t           gRxBuffer[McSPIRX_DATA_COUNT];
    // static uint32_t mcspi_address_rx = 0;
    uint32_t spi_initDoneFlag_rx = 0;
    // static uint32_t is_tda4a = 0;//1-a芯片,0-b芯片
    /* ========================================================================== */
    /**/
    /* ========================================================================== */
    
    
    typedef struct tivxSpirxParams_t tivxSpirxParams;
    
    struct tivxSpirxParams_t{
        SPI_TransferMode    transferMode;       /*!< Blocking or Callback mode */
        uint32_t            transferTimeout;    /*!< Transfer timeout in system
                                                     ticks (Not supported with all
                                                     implementations */
        SPI_CallbackFxn     transferCallbackFxn;/*!< Callback function pointer */
        SPI_Mode            mode;               /*!< Master or Slave mode */
        uint32_t            bitRate;            /*!< SPI bit rate in Hz */
        uint32_t            mcspirxIdx;
        uint32_t            dataSize;           /*!< SPI data frame size in bits */
        SPI_FrameFormat     frameFormat;        /*!< SPI frame format */
        void               *custom;             /*!< Custom argument used by driver
                                                     implementation */
    };
    
    
    static tivx_target_kernel vx_spirx_target_kernel = NULL;
    
    
    static vx_status VX_CALLBACK tivxspiRxProcess(
           tivx_target_kernel_instance kernel,
           tivx_obj_desc_t *obj_desc[],
           uint16_t num_params, void *priv_arg);
    static vx_status VX_CALLBACK tivxspiRxCreate(
           tivx_target_kernel_instance kernel,
           tivx_obj_desc_t *obj_desc[],
           uint16_t num_params, void *priv_arg);
    static vx_status VX_CALLBACK tivxspirxDelete(
           tivx_target_kernel_instance kernel,
           tivx_obj_desc_t *obj_desc[],
           uint16_t num_params, void *priv_arg);
    static vx_status VX_CALLBACK tivxspirxControl(
           tivx_target_kernel_instance kernel,
           uint32_t node_cmd_id, tivx_obj_desc_t *obj_desc[],
           uint16_t num_params, void *priv_arg);
    
    
    
    extern void Board_delay(uint32_t delayCycles);
    
    // static void McSPIMSPolledModeTransfer(uint16_t length)
    // {
    //     uint32_t          channelStatus = 0;
    //     volatile uint32_t timeout1      = 0xFFFFU;
    //     uint8_t          *p_rx;
    //     // uint32_t count;
    
    //     p_rx    = gRxBuffer;
    
    
    //     // do{
    //         while (0 != length)
    //         {
    //             timeout1      = 0xFFFF;
    //             channelStatus = McSPIChannelStatusGet(mcspi_address_rx, gChNum_rx);
    //             while (0 == (channelStatus & CSL_MCSPI_CH0STAT_RXS_MASK))
    //             {
    //                 channelStatus = 0;
    //                 channelStatus = McSPIChannelStatusGet(mcspi_address_rx, gChNum_rx);
    
    //                 --timeout1;
    //                 if (0 == timeout1)
    //                 {
    //                     // printf("\nMCU McSPI2 RX Timed out!!");
    //                     Board_delay(20);
    //                     break;
    //                 }
    //             }
    //                 *p_rx++ = (uint8_t)McSPIReceiveData(mcspi_address_rx, gChNum_rx);
    //                 length--;
    //         }
    
    //         length = McSPIRX_DATA_COUNT;
    
    //         // for(count =0; count < 3; count ++){
    //         //     if(mcspi_address_rx == 0x2120000){
    //         //         printf("MCSPI2 SLAVE MODE RECV BUFFER address= 0x%x, recv value = %d\n", mcspi_address_rx, gRxBuffer[count]);
    //         //     }
    //         //     // VX_PRINT(VX_ZONE_ERROR, "rx_node======= recv %d = %d\n", count,(uint32_t)(gRxBuffer[count]));
    //         //     // gRxBuffer[count] = 0;
    //         // }
    //         Board_delay(2);
    //     // }while(channelStatus != 1000);
    // }
    
    
    // static void slave_SPI1SetUp(void)
    // {
    //     /* Reset the McSPI instance.*/
    //     McSPIReset(mcspi_address_rx);
    
    //     /* AUTOIDLE      bit - Disable (OCP clock is running free, no gating)  */
    //     MCSPISysConfigSetup(mcspi_address_rx, MCSPI_CLOCKS_OCP_ON_FUNC_ON,
    //                         MCSPI_SIDLEMODE_NO, MCSPI_WAKEUP_DISABLE,
    //                         MCSPI_AUTOIDLE_OFF);
    
    //     /* Enable chip select pin.*/
    //     McSPICSEnable(mcspi_address_rx);
    
    //     /* Enable slave mode of operation.*/
    //     McSPISlaveModeEnable(mcspi_address_rx);
    
    
    // #ifdef gMcSpi_tda4AMaster_to_tda4BSlave
    //     /* Configure the Pin Direction.*/
    //     MCSPIPinDirSet(mcspi_address_rx, MCSPI_RX_ONLY_MODE,
    //                             MCSPI_DATA_LINE_COMM_MODE_1, gChNum_rx);
    // #else
    //     /* Configure the Pin Direction.*/
    //     MCSPIPinDirSet(mcspi_address_rx, MCSPI_RX_ONLY_MODE,
    //                                 MCSPI_DATA_LINE_COMM_MODE_6, gChNum_rx);
    // #endif
    
    //     McSPIClkConfig(mcspi_address_rx, MCSPIRX_IN_CLK, MCSPIRX_OUT_CLK, gChNum_rx,
    //                    MCSPI_CLK_MODE_1);
    
    //     /* Configure the word length.*/
    //     McSPIWordLengthSet(mcspi_address_rx, MCSPI_WORD_LENGTH(8), gChNum_rx);
    
    //     /* Set polarity of SPIEN to low.*/
    //     McSPICSPolarityConfig(mcspi_address_rx,
    //                           (MCSPI_CH0CONF_EPOL_ACTIVELOW <<
    //                            MCSPI_CH0CONF_EPOL_SHIFT), gChNum_rx);
    
    
    //     McSPIRxFIFOConfig(mcspi_address_rx, MCSPI_RX_FIFO_ENABLE, gChNum_rx);
    //     McSPITxFIFOConfig(mcspi_address_rx, MCSPI_TX_FIFO_DISABLE, gChNum_rx);
    
    
    //     McSPIFIFOTrigLvlSet(mcspi_address_rx, 128, 1, MCSPI_RX_ONLY_MODE);
    
    //     McSPIChannelEnable(mcspi_address_rx, gChNum_rx);
    // }
    
    
    extern void Board_delay(uint32_t delayCycles);
    
    /* Test channel # */
    #define MCSPI_TEST_CHN 0
    
    #define SPI_TEST_ID_INT 1
    
    static MCSPI_Handle spi;
    static uint32_t xferLen = 64; /*length of information*/
    
    typedef struct spi_Config_s{
        bool     (*testFunc)(void *);
        int32_t  testId;
        bool     master;
        bool     pollMode;
        bool     cbMode;
        bool     dmaMode;
        uint32_t timeout;
        char     testDesc[80];
        uint32_t param;
        uint32_t trigLvl;
    
    }SPI_ConfigEx;
    
    SPI_ConfigEx SPI_Configs = {
        NULL,
        SPI_TEST_ID_INT,
        false,
        false,
        false,
        false,
        0,
        NULL,
        1,
        64
    };
    
    /* Default MCSPI parameters structure */
    const MCSPI_Params app_MCSPI1_defaultParams = {
        SPI_MODE_BLOCKING,  /* transferMode */
        0U,                 /* transferTimeout */
        NULL,               /* transferCallbackFxn */
        SPI_SLAVE,         /* mode */
        10000000,            /* bitRate */
        8,                  /* dataSize */
        SPI_POL0_PHA1,      /* frameFormat */
        NULL                /* custom */
    };
    
    const MCSPI_Params app_MCSPI2_defaultParams = {
        SPI_MODE_BLOCKING,  /* transferMode */
        0U,                 /* transferTimeout */
        NULL,               /* transferCallbackFxn */
        SPI_SLAVE,         /* mode */
        10000000,            /* bitRate */
        8,                  /* dataSize */
        SPI_POL0_PHA1,      /* frameFormat */
        NULL                /* custom */
    };
    
    static void MCSPI_InitConfig(uint32_t instance, int32_t Id, uint32_t chn, bool multiChn)
    {
        SPI_HWAttrs spi_cfg;
        // int32_t     testId = Id;
    
        /* Get the default SPI init configurations */
        SPI_socGetInitCfg(instance, &spi_cfg);
    
        printf("instance = %d\n", instance);
        printf("spi_cfg.baseAddr = 0x%x\n", spi_cfg.baseAddr);
        printf("spi_cfg.intNum = %d\n", spi_cfg.intNum);
        /*
         * Set blocking mode (dma mode or non-dma interrupt mode)
         * or callback mode
         */
    
        /* interrupt enabled */
        spi_cfg.enableIntr = FALSE;
        spi_cfg.edmaHandle = NULL;
        spi_cfg.dmaMode    = FALSE;
    
        /* Set the SPI init configurations */
        SPI_socSetInitCfg(instance, &spi_cfg);
    }
    
    static void MCSPI_Params_Init(MCSPI_Params *params, uint32_t instance)
    {
        if ((params != NULL) && (instance == 1)){
            *params = app_MCSPI1_defaultParams;
        }else if((params != NULL) && (instance == 2)){
            *params = app_MCSPI2_defaultParams;
        }
    }
    
    /* Transaction data */
    SPI_Transaction   transaction;
    unsigned char masterRxBuffer[128] __attribute__ ((aligned (128)));
    static uint32_t instance = 1;
    
    #define CANCEL_TX_LEN   (1024)
    unsigned char masterTxBuffer[128] = "PASS: Txd from master SPI PASS: Txd from master SPI PASS: Txd from master SPI ";
    uint8_t slave1TxBuffer[128];
    // uint8_t slave1RxBuffer[128];
    uint8_t slave2TxBuffer[128];
    uint8_t slave2RxBuffer[128];
    uint8_t checkRxBuffer[128];
    
    
    uint8_t array_ptr[BUFFER_RECV_COUNT][128];
    #define DEBUG_YU
    
    static bool SPI_mst_slv_xfer(void *spi, SPI_ConfigEx *test, uint32_t xferLen, uint32_t instance, uint8_t *rxBuffer)
    {
        uintptr_t        addrMasterRxBuf, addrMasterTxBuf;// addrSlaveRxBuf, addrSlaveTxBuf;// addrCancelTxBuff, addrCancelRxBuff;
        bool            ret = false;
        uint32_t        terminateXfer = 1;
        bool            master = test->master;
    
        addrMasterRxBuf = (uintptr_t)masterRxBuffer;
        addrMasterTxBuf = (uintptr_t)masterTxBuffer;
    
        memset(slave1TxBuffer, 0, sizeof(slave1TxBuffer));
        // memset(slave1RxBuffer, 0, sizeof(slave1RxBuffer));
        memset(rxBuffer, 0, xferLen);
        memset(slave2TxBuffer, 0, sizeof(slave2TxBuffer));
        memset(slave2RxBuffer, 0, sizeof(slave2RxBuffer));
        /* Initialize slave SPI transaction structure */
        transaction.count = xferLen;
        transaction.arg = (void *)&terminateXfer;
        if (master == true)
        {
            transaction.txBuf = (void *)addrMasterTxBuf;
            transaction.rxBuf = (void *)addrMasterRxBuf;
        }
        else
        {
            if(instance == 1){
                // transaction.txBuf = (void *)slave1TxBuffer;
                // transaction.rxBuf = (void *)slave1RxBuffer;
                transaction.rxBuf = (void *)rxBuffer;
            }else if(instance == 2){
                transaction.txBuf = (void *)slave2TxBuffer;
                transaction.rxBuf = (void *)slave2RxBuffer;
            }
        }
    
        ret = MCSPI_transfer((MCSPI_Handle)spi, &transaction);    
    
    
    
        // ret = true;
        return ret;
    }
    
    
    #define SPIRX_TARGET_RX_DATA_EVENT     (Event_Id_00)
    // static uint32_t spiRxEvent = 0;
    static uint32_t spiRxEventCnt = 0;
    void MCSPI_transferCallback(MCSPI_Handle mcHandle, SPI_Transaction *transaction){
        Event_post(gSpirxIntrEvent, SPIRX_TARGET_RX_DATA_EVENT);
        // spiRxEvent = 1;
        spiRxEventCnt++;
    }
    
    static void mcSpiInit(uint32_t instance, MCSPI_Params *spiParams){
        
        // uint32_t instance = 1; /*instance number represent MCSPI0,MCSPI1,MCSPI2*/
    
        MCSPI_InitConfig(instance, SPI_Configs.testId, MCSPI_TEST_CHN, false);
        MCSPI_Params_Init(spiParams, instance);
    
        spiParams->transferCallbackFxn = MCSPI_transferCallback;
    
        uint32_t timeout = SPI_Configs.timeout;
        spiParams->transferTimeout = timeout;
    
        spi = MCSPI_open(instance, MCSPI_TEST_CHN, spiParams);
        if (spi == NULL)
        {
            VX_PRINT(VX_ZONE_ERROR,"Error initializing SPI\n");
        }
        else
        {
            VX_PRINT(VX_ZONE_ERROR,"SPI initialized\n");
        }
    }
    
    
    
    static vx_status VX_CALLBACK tivxspiRxCreate(
           tivx_target_kernel_instance kernel,
           tivx_obj_desc_t *obj_desc[],
           uint16_t num_params, void *priv_arg)
    {
        vx_status status = (vx_status)VX_SUCCESS;
        tivx_obj_desc_user_data_object_t *input_cfg_obj_desc;
        tivxSpirxParams *prms = NULL;
        void *spirx_config_target_ptr;
        tivx_spirx_params_t *params; 
        uint32_t index;
    
        for(index = 0; index < 128; index++){
            checkRxBuffer[index] = index;
        }
        
        if ( (num_params != TIVX_KERNEL_SPIRX_MAX_PARAMS)
            || (NULL == obj_desc[TIVX_KERNEL_SPIRX_INPUT_CFG_IDX])
            || (NULL == obj_desc[TIVX_KERNEL_SPIRX_OUTPUT_DATA_IDX])
        )
        {
            status = (vx_status)VX_FAILURE;
        }
        else
        {
            input_cfg_obj_desc = (tivx_obj_desc_user_data_object_t *)obj_desc[TIVX_KERNEL_SPIRX_INPUT_CFG_IDX];
    
            prms = tivxMemAlloc(sizeof(tivxSpirxParams), (vx_enum)TIVX_MEM_EXTERNAL);
            if (NULL != prms){
                memset(prms, 0, sizeof(tivxSpirxParams));
            }
            spirx_config_target_ptr = tivxMemShared2TargetPtr(&input_cfg_obj_desc->mem_ptr);
    
            tivxMemBufferMap(spirx_config_target_ptr, input_cfg_obj_desc->mem_size,
                                (vx_enum)VX_MEMORY_TYPE_HOST, (vx_enum)VX_READ_ONLY);
    
            params = (tivx_spirx_params_t *)spirx_config_target_ptr;
            printf("creat spi params = %d\n", params->mspiIdx);
    
            Event_Params eventParams;
    
            Event_Params_init(&eventParams);
            Event_construct(&gSpirxIntrEventMem, &eventParams);
            gSpirxIntrEvent =  Event_handle(&gSpirxIntrEventMem);
    
            MCSPI_Params spi1Params;
            mcSpiInit(instance, &spi1Params);
    
            tivxMemBufferUnmap(spirx_config_target_ptr,
                                input_cfg_obj_desc->mem_size, (vx_enum)VX_MEMORY_TYPE_HOST,
                                (vx_enum)VX_READ_ONLY);
        }
        return status;
    }
    
    uint8_t pdk_data[1];
    
    static vx_status VX_CALLBACK tivxspiRxProcess(
           tivx_target_kernel_instance kernel,
           tivx_obj_desc_t *obj_desc[],
           uint16_t num_params, void *priv_arg)
    {
        vx_status status = (vx_status)VX_SUCCESS;
        // tivxSpirxParams *prms = NULL;
        // vx_uint32 size;
        tivx_spirx_recvSlamCarInfo_t *mspiRecvData; 
        tivx_obj_desc_user_data_object_t *src_desc0;
        // uint16_t i = 0;
        // UInt postedEvents;
        // SPI_v1_HWAttrs const *hwAttrs;
        if ( (num_params != TIVX_KERNEL_SPIRX_MAX_PARAMS)
            || (NULL == obj_desc[TIVX_KERNEL_SPIRX_INPUT_CFG_IDX])
            || (NULL == obj_desc[TIVX_KERNEL_SPIRX_OUTPUT_DATA_IDX])
        )
        {
            status = (vx_status)VX_FAILURE;
        }
    
        memset(pdk_data, 0, 1);
    
        if((vx_status)VX_SUCCESS == status)
        {
            void *src_desc0_target_ptr;
    
            src_desc0 = (tivx_obj_desc_user_data_object_t *)obj_desc[TIVX_KERNEL_SPIRX_OUTPUT_DATA_IDX];
            src_desc0_target_ptr = tivxMemShared2TargetPtr(&src_desc0->mem_ptr);
    
            /* Map all buffers, which invalidates the cache */
            tivxMemBufferMap(src_desc0_target_ptr,
                src_desc0->mem_size, VX_MEMORY_TYPE_HOST,
                VX_READ_ONLY);
            mspiRecvData = (tivx_spirx_recvSlamCarInfo_t *)src_desc0_target_ptr;
            if (SPI_mst_slv_xfer((void *)spi, &SPI_Configs, xferLen, instance, mspiRecvData->checkBuffer) == false){
                VX_PRINT(VX_ZONE_ERROR,"Error transfer SPI\n");
                VX_PRINT(VX_ZONE_ERROR,"SPI_mst_slv_xfer err mspiRecvData pdvSpiStatus = %d\n", mspiRecvData->pdvSpiStatus);
            }              
    
            // hwAttrs = (const SPI_v1_HWAttrs *)spi->handle->hwAttrs;
            // VX_PRINT(VX_ZONE_ERROR, "step 0 \n");
            // while((spiRxEvent == 0) && (i++ < 100))
            // {
            //     tivxTaskWaitMsecs(1);
            // };
            // i = 0;
            // spiRxEvent = 0;
            // VX_PRINT(VX_ZONE_ERROR, "step 1 Cnt %d\n", spiRxEventCnt);
            #if 0
            postedEvents = Event_pend(gSpirxIntrEvent,0,
                                SPIRX_TARGET_RX_DATA_EVENT,
                                BIOS_WAIT_FOREVER);
    
            if(postedEvents & SPIRX_TARGET_RX_DATA_EVENT){
          
            }
            #endif
            // tivxTaskWaitMsecs(1);
    
            tivxMemBufferUnmap(src_desc0_target_ptr, src_desc0->mem_size, VX_MEMORY_TYPE_HOST, VX_WRITE_ONLY);
        }
    
    
    
    
        return status;
    }
    
    
    
    
    static vx_status VX_CALLBACK tivxspirxDelete(
           tivx_target_kernel_instance kernel,
           tivx_obj_desc_t *obj_desc[],
           uint16_t num_params, void *priv_arg)
    {
        vx_status status = (vx_status)VX_SUCCESS;
    
        return status;
    }
    
    
    void tivxAddTargetKernelSpirx(void)
    {
        char target_name[TIVX_TARGET_MAX_NAME];
        vx_enum self_cpu;
    
        self_cpu = tivxGetSelfCpuId();
    
        // if((self_cpu == (vx_enum)TIVX_CPU_ID_IPU1_0) || (self_cpu == (vx_enum)TIVX_CPU_ID_IPU1_1))
        if((self_cpu == (vx_enum)TIVX_CPU_ID_IPU1_1))
        {
            strncpy(target_name, TIVX_TARGET_SPIRX, TIVX_TARGET_MAX_NAME);
            vx_spirx_target_kernel = tivxAddTargetKernelByName(
                                TIVX_KERNEL_SPIRX_NAME,
                                target_name,
                                tivxspiRxProcess,
                                tivxspiRxCreate,
                                tivxspirxDelete,
                                tivxspirxControl,
                                NULL);
    
        }
    }
    
    void tivxRemoveTargetKernelSpiRx(void)
    {
        vx_status status = (vx_status)VX_SUCCESS;
    
        status = tivxRemoveTargetKernel(vx_spirx_target_kernel);
        if(status == (vx_status)VX_SUCCESS)
        {
            vx_spirx_target_kernel = NULL;
        }
    
    }
    
    
    static vx_status VX_CALLBACK tivxspirxControl(
           tivx_target_kernel_instance kernel,
           uint32_t node_cmd_id, tivx_obj_desc_t *obj_desc[],
           uint16_t num_params, void *priv_arg)
    {
        vx_status status = (vx_status)VX_SUCCESS;
        return status;
    }
    
    
    

    Regards,

    Jason

  • Hi Brijesh,

          There are two types of interrupts, FIR and IRQ. I don't know which type of SPI RX interrupt should be? Can we set it as FIR interrupt? 

    Regards,

    Jason

  • Hi Jason,

    SPI uses IRQ interrupts. 

    Why do you want to set FIQ interrupt? 

    I still have not got the chance to review your code, will do it next week.

    Regards,

    Brijesh

  • Hi Jason,

    Any further update on this thread?

    Regards,

    Brijesh

  • Closing this thread