CMSIS LPSPI Driver

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

CMSIS LPSPI Driver

Jump to solution
227 Views
farazahmed
NXP Employee
NXP Employee

Hello everyone, I am using SDK example mcxn9xxevk_cmsis_lpspi_edma_b2b_transfer_master for MCX-N947-EVK. I am trying to achieve SPI read and write in 16 clock cycles as shown in picture for the accelerometer ism330dlc.

farazahmed_0-1713794501002.pngfarazahmed_1-1713794524666.png

I have setup ARM_SPI_SS_MASTER_SW for the SPI SS pin control and tried to set it low/high manual before sending and receiving packet. The sequence of transmission is defined in platform_write and platform_read function.

/*

 * Copyright 2017 NXP

 * All rights reserved.

 *

 * SPDX-License-Identifier: BSD-3-Clause

 */



#include "fsl_device_registers.h"

#include "fsl_debug_console.h"

#include "fsl_lpspi_cmsis.h"

#include "pin_mux.h"

#include "clock_config.h"

#include "board.h"

#include "ism330dlc_reg.h"



/*******************************************************************************

 * Definitions

 ******************************************************************************/

/* Master related */

#define DRIVER_MASTER_SPI Driver_SPI1

#define EXAMPLE_LPSPI_DEALY_COUNT 0xfffffU

#define EXAMPLE_LPSPI_MASTER_DMA_BASEADDR DMA0

#define EXAMPLE_LPSPI_DMA_CLOCK kCLOCK_Dma0

#define EXAMPLE_LPSPI_CLOCK_FREQ CLOCK_GetLPFlexCommClkFreq(1u)

#define TRANSFER_SIZE 64U /* Transfer dataSize */

#define TRANSFER_BAUDRATE 500000U /* Transfer baudrate - 500k */



/*******************************************************************************

 * Prototypes

 ******************************************************************************/

/* LPSPI user SignalEvent */

void LPSPI_MasterSignalEvent_t(uint32_t event);



/*******************************************************************************

 * Variables

 ******************************************************************************/



AT_NONCACHEABLE_SECTION_INIT(uint8_t masterRxData[TRANSFER_SIZE]) = {0};

AT_NONCACHEABLE_SECTION_INIT(uint8_t masterTxData[TRANSFER_SIZE]) = {0};



volatile bool isTransferCompleted = false;

volatile bool isMasterOnTransmit = false;

volatile bool isMasterOnReceive = false;

volatile uint32_t g_systickCounter = 20U;

/*******************************************************************************

 * Code

 ******************************************************************************/

int32_t platform_write(void *handle, uint8_t Reg, const uint8_t *Bufp, uint16_t len);

int32_t platform_read(void *handle, uint8_t Reg, uint8_t *Bufp, uint16_t len);





uint32_t LPSPI1_GetFreq()

{

return EXAMPLE_LPSPI_CLOCK_FREQ;

}

void SysTick_Handler(void)

{

if (g_systickCounter != 0U)

 {

 g_systickCounter--;

 }

}



void LPSPI_MasterSignalEvent_t(uint32_t event)

{

if (true == isMasterOnReceive)

 {

 isMasterOnReceive = false;

 }

if (true == isMasterOnTransmit)

 {

 isMasterOnTransmit = false;

 }

 isTransferCompleted = true;

}



/*!

 * @brief Main function

 */

int main(void)

{

/* attach FRO 12M to FLEXCOMM4 (debug console) */

 CLOCK_SetClkDiv(kCLOCK_DivFlexcom4Clk, 1u);

 CLOCK_AttachClk(BOARD_DEBUG_UART_CLK_ATTACH);



/* attach FRO 12M to FLEXCOMM1 */

 CLOCK_SetClkDiv(kCLOCK_DivFlexcom1Clk, 1u);

 CLOCK_AttachClk(kFRO12M_to_FLEXCOMM1);



/* Enable DMA clock. */

 CLOCK_EnableClock(EXAMPLE_LPSPI_DMA_CLOCK);





 BOARD_InitBootPins();

 BOARD_InitBootClocks();

 BOARD_InitDebugConsole();





/* DMA Mux init and EDMA init */

edma_config_t edmaConfig = {0};

 EDMA_GetDefaultConfig(&edmaConfig);

#if defined(BOARD_GetEDMAConfig)

 BOARD_GetEDMAConfig(edmaConfig);

#endif

 EDMA_Init(EXAMPLE_LPSPI_MASTER_DMA_BASEADDR, &edmaConfig);



#if (defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT)

 DMAMUX_Init(EXAMPLE_LPSPI_MASTER_DMA_MUX_BASEADDR);

#endif

uint32_t errorCount;

uint32_t loopCount = 1U;

uint32_t i;

static uint8_t whoamI=0;



stmdev_ctx_t dev_ctx; /** xxxxxxx is the used part number **/

 dev_ctx.write_reg = platform_write;

 dev_ctx.read_reg = platform_read;

dev_ctx.handle = &DRIVER_MASTER_SPI;



/*LPSPI master init*/

 DRIVER_MASTER_SPI.Initialize(LPSPI_MasterSignalEvent_t);

 DRIVER_MASTER_SPI.PowerControl(ARM_POWER_FULL);



//DRIVER_MASTER_SPI.Control(ARM_SPI_MODE_MASTER, TRANSFER_BAUDRATE);

 DRIVER_MASTER_SPI.Control(ARM_SPI_MODE_MASTER | ARM_SPI_CPOL0_CPHA0| ARM_SPI_DATA_BITS(8)| ARM_SPI_MSB_LSB| ARM_SPI_SS_MASTER_SW,TRANSFER_BAUDRATE);



 DRIVER_MASTER_SPI.Control(ARM_SPI_CONTROL_SS, ARM_SPI_SS_INACTIVE);

while (1)

 {

ism330dlc_xl_data_rate_set(&dev_ctx, ISM330DLC_XL_ODR_12Hz5);



/* Delay */

if (SysTick_Config(SystemCoreClock / 1000U))

 {

while (1)

 {

 }

 }

/* Delay 1 ms */

 g_systickCounter = 1U;

while (g_systickCounter != 0U)

 {

 }



 }

}

int32_t platform_write(void *handle, uint8_t reg, const uint8_t *bufp, uint16_t len)

{

 isTransferCompleted = false;

 isMasterOnTransmit = true;

 DRIVER_MASTER_SPI.Control(ARM_SPI_CONTROL_SS,ARM_SPI_SS_ACTIVE);

 DRIVER_MASTER_SPI.Send(&reg, 1U);

while (!isTransferCompleted)

 {

 }

 isTransferCompleted = false;

 isMasterOnTransmit = true;

 DRIVER_MASTER_SPI.Send((uint8_t*) bufp, 1U);

 DRIVER_MASTER_SPI.Control(ARM_SPI_CONTROL_SS,ARM_SPI_SS_INACTIVE);

while (!isTransferCompleted)

 {

 }



return 0;



}

int32_t platform_read(void *handle, uint8_t reg, uint8_t *bufp, uint16_t len)

{

 reg|=0x80;

 isTransferCompleted = false;

 isMasterOnTransmit = true;

 DRIVER_MASTER_SPI.Control(ARM_SPI_CONTROL_SS,ARM_SPI_SS_ACTIVE);

 DRIVER_MASTER_SPI.Send(&reg, 1U);

while (!isTransferCompleted)

 {

 }

 isTransferCompleted = false;

 isMasterOnReceive = true;

 DRIVER_MASTER_SPI.Receive((uint8_t*) bufp,len);

while (!isTransferCompleted)

 {

 }

 DRIVER_MASTER_SPI.Control(ARM_SPI_CONTROL_SS,ARM_SPI_SS_INACTIVE);

return 0;

}


the ism330dlc_xl_data_rate_set function implementation is:

int32_t ism330dlc_xl_data_rate_set(const stmdev_ctx_t *ctx,

ism330dlc_odr_xl_t val)

{

ism330dlc_ctrl1_xl_t ctrl1_xl;

int32_t ret;

ret = ism330dlc_read_reg(ctx, ISM330DLC_CTRL1_XL,

(uint8_t *)&ctrl1_xl, 1);



if (ret == 0)

{

ctrl1_xl.odr_xl = (uint8_t) val;

ret = ism330dlc_write_reg(ctx, ISM330DLC_CTRL1_XL,

(uint8_t *)&ctrl1_xl, 1);

}



return ret;

}

this function call platform_write and platform_read for the ism330dlc_write_reg/ism330dlc_read_reg.


farazahmed_2-1713795063085.png

The yellow marked one is the read cycle and the read one is the write cycle.
The CS pin is pulled back to high after sending the register value for reading register value from the slave.
Please guide.

 

0 Kudos
1 Solution
127 Views
farazahmed
NXP Employee
NXP Employee

I shifted to SDK example mcxn9xxevk_lpspi_edma_b2b_transfer_master.
The CS pin is pulled high after each byte transfer in the default example. 

To solve this, I added this before beginning of every transfer. Now, the CS is kept low during the whole transmission.

LPSPI_SetPCSContinous(EXAMPLE_LPSPI_MASTER_BASEADDR, (uint8_t)1);

 

 

View solution in original post

0 Kudos
3 Replies
212 Views
farazahmed
NXP Employee
NXP Employee

farazahmed_0-1713795876492.png

 

0 Kudos
142 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi,

I have checked your code, it appears this is not SDK example code.

If you want to set the SPI in master mode and use DMA to transfer code, I suppose that you can not use a GPIO as CS signal to select slave spi device. You have to use FC_PCSx signal to connect /CS of slave SPI, which is driven automatically when the SPI master transfers data, it toggles for each byte or word.

If you do want to use GPIO pin, I suppose you can clear the GPIO before the DMA transfers data, after all data has been transferred, you can set the GPIO. The drawback of the method is GPIO is kept low during the transferring process.

This is the pin assignment for SPI_PCSx

xiangjun_rong_0-1713843555182.png

Hope it can help you

BR

XiangJun Rong

0 Kudos
128 Views
farazahmed
NXP Employee
NXP Employee

I shifted to SDK example mcxn9xxevk_lpspi_edma_b2b_transfer_master.
The CS pin is pulled high after each byte transfer in the default example. 

To solve this, I added this before beginning of every transfer. Now, the CS is kept low during the whole transmission.

LPSPI_SetPCSContinous(EXAMPLE_LPSPI_MASTER_BASEADDR, (uint8_t)1);

 

 

0 Kudos