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(¶ms);
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, ¶ms);
VX_PRINT(VX_ZONE_ERROR, "app_run_task_create close rx!!\r\n");
// tivxTaskSetDefaultCreateParams(¶ms);
// 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, ¶ms);
tivxTaskSetDefaultCreateParams(¶ms);
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, ¶ms);
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

