AnsweredAssumed Answered

KSDK DSPI PCS to CLK delay scaler

Question asked by PETER SHIH on Oct 27, 2015
Latest reply on Dec 8, 2015 by PETER SHIH

Hi:

 

I am working on a custom board equipped with K66 MCU, serial Flash, and other peripherals. The purpose of serial Flash is just for data storage. I have successfully read the device JEDEC ID through DSPI bus. However, based on the scope observation, the delay between the chip enable (PCS) to clock (CLK) is too long (approximately  39us). Please refer to the following scope screenshot,

Yellow signal: PCS0 on DSPI1,

Green signal: SIN,

Blue signal: CLK, and

Pink signal: SOUT.

 

Based on the datasheet, the delay between the PCS to the first raising clock can be adjusted by bit15-12 PCS to SCK Delay Scaler in the SPIx_CTARn register. The delay is calculated by tcsc=(1/fp)*PCSSCK*CSSCK. I have K66 running at 120MHz clock and the system speed is 60MHz. That means the minimum delay should be (1/60M)*1*2=32ns.

The software development is based on KDS3.0 and KSDK1.2. I don't have any special delay settings (DSPI_DRV_MasterSetDelay()) in the source code, and I have verified the PCSSCK=00 and CSSCK=1 in the CTAR1 from DSPI1, which should be (1/60M)*1*4=64ns. This value, initial set from  DSPI_HAL_SetDelay(base, userConfig->whichCtar, 0, 1, kDspiPcsToSck) in the DSPI_DRV_MasterInit(), doesn't match the signal I saw on the scope. I wonder if I misunderstand somewhere. Is any way I can short the time between the PCS and the 1st CLK? Please let me know if you have any idea or recommendation. Thanks!

 

#include <stdio.h> #include "main.h" #include "ethSwitch.h" #include "W25QxFVFlashDriver.h"  //----------------------------------------------------------------------- // Function Prototypes //----------------------------------------------------------------------- void main_task(uint32_t param); void task_example(task_param_t param); void gpio_Init(void);  //----------------------------------------------------------------------- // Constants //----------------------------------------------------------------------- #define MAIN_TASK              8U const TASK_TEMPLATE_STRUCT  MQX_template_list[] = {    { MAIN_TASK, main_task, 0xC00, 20, "main_task", MQX_AUTO_START_TASK},    { 0L,        0L,        0L,    0L,  0L,         0L } }; #define TASK_EXAMPLE_PRIO            6U #define TASK_EXAMPLE_STACK_SIZE   1024U  //----------------------------------------------------------------------- // Macros //----------------------------------------------------------------------- OSA_TASK_DEFINE(task_example, TASK_EXAMPLE_STACK_SIZE);  //----------------------------------------------------------------------- // Main Function //----------------------------------------------------------------------- void main_task(uint32_t param) {     uint32_t    int32utmp;     osa_status_t result = kStatus_OSA_Error;      printf("\n\nRunning the SPIFFS project.");      // Configure SPI pins     configure_spi_pins(BOARD_ETHSW_SERFLASH_SPI_INSTANCE);    //configure SPI1 for Ethernet switch     gpio_Init();      /* Initialize Ethernet Switch KSZ8895RQ */     OSA_TimeDelay(100);        //wait for Ethernet switch ready     Initialize_EthSW();      int32utmp = W25Q128FV_ReadID();     if (int32utmp == 0xEF4018)    printf("\nW25Q128FV is detected.");      OSA_Init();  //    result = OSA_TaskCreate(task_example, //                    (uint8_t *)"example", //                    TASK_EXAMPLE_STACK_SIZE, //                    task_example_stack, //                    TASK_EXAMPLE_PRIO, //                    (task_param_t)0, //                    false, //                    &task_example_task_handler); //    if (result != kStatus_OSA_Success) //    { //        printf("Failed to create example task\r\n"); //        return; //    }      OSA_Start();      for (;;)                                         // Forever loop     {         OSA_TimeDelay(100);        //500ms delay     }   } //----------------------------------------------------------------------- // Task Functions //----------------------------------------------------------------------- // //void task_example(task_param_t param) //{ //    printf("\r\nHellow World.\r\n"); // //    while(1) //    { //        __asm("NOP"); //    } //}  void gpio_Init(void) {     gpio_output_pin_user_config_t     outputPinConfig;      outputPinConfig.pinName = kGpioC5;     outputPinConfig.config.outputLogic = 1;     outputPinConfig.config.slewRate = kPortSlowSlewRate;     outputPinConfig.config.isOpenDrainEnabled = false;     outputPinConfig.config.driveStrength = kPortLowDriveStrength;     GPIO_DRV_OutputPinInit(&outputPinConfig);      outputPinConfig.pinName = kGpioC6;     outputPinConfig.config.outputLogic = 1;     outputPinConfig.config.slewRate = kPortSlowSlewRate;     outputPinConfig.config.isOpenDrainEnabled = false;     outputPinConfig.config.driveStrength = kPortLowDriveStrength;     GPIO_DRV_OutputPinInit(&outputPinConfig); }

 

uint32_t W25Q128FV_ReadID(void) {     uint8_t            send_buf[5];     uint8_t            recv_buf[5];     uint32_t         result;      result = dspicomm_w25qxf_init(DSPI_W25QxFV_INSTANCE, TRANSFER_HIGH_BAUDRATE);     if (result != kStatus_DSPI_Success)    return (-1);      send_buf[0] = JEDEC_ID;     result = dspicomm_read(DSPI_W25QxFV_INSTANCE, send_buf, 1, recv_buf, 3);     dspicomm_close(DSPI_W25QxFV_INSTANCE);      result = (uint32_t)(recv_buf[1] << 16);    // Manuf ID     : Winbond             = 0xEF     result |= recv_buf[2] << 8;                // Memory Type     : SPI Serial Flash     = 0x40     result |= recv_buf[3];                   // Memory Size     : W25Q128FV         = 0x18      return result; }  int8_t dspicomm_w25qxf_init(uint32_t instance, uint32_t speed) {     dspi_status_t dspiResult;     uint32_t calculatedBaudRate;          w25Q128FV_masterUserConfig.isChipSelectContinuous    = true;     w25Q128FV_masterUserConfig.isSckContinuous        = false;     w25Q128FV_masterUserConfig.pcsPolarity            = kDspiPcs_ActiveLow;     w25Q128FV_masterUserConfig.whichCtar              = kDspiCtar1;     w25Q128FV_masterUserConfig.whichPcs               = kDspiPcs0;      // Initialize master driver.     dspiResult = DSPI_DRV_MasterInit(instance,                                      &w25Q128FV_masterState,                                      &w25Q128FV_masterUserConfig);     if (dspiResult != kStatus_DSPI_Success)     {         printf("\r\nERROR: Can not initialize SPI master driver!");         return -1;     }      // Setup the configuration.     w25Q128FV_masterDevice.dataBusConfig.bitsPerFrame = 8;     w25Q128FV_masterDevice.dataBusConfig.clkPhase     = kDspiClockPhase_FirstEdge;     w25Q128FV_masterDevice.dataBusConfig.clkPolarity  = kDspiClockPolarity_ActiveHigh;     w25Q128FV_masterDevice.dataBusConfig.direction    = kDspiMsbFirst;     w25Q128FV_masterDevice.bitsPerSec = speed;     dspiResult = DSPI_DRV_MasterConfigureBus(instance,                                              &w25Q128FV_masterDevice,                                              &calculatedBaudRate);     if (dspiResult != kStatus_DSPI_Success)     {         printf("\r\nERROR: failure in configuration SPI bus!");         return -1;     }  //    /* Configure timing delays 200ns, it is optional, useful for slower peripheral diveces or "fine tune" SPI timings */ //    uint32_t delayInNanosec = 200; //    uint32_t calculatedDelay; //    /* Set pcs to sck delay */ //    DSPI_DRV_MasterSetDelay(instance, kDspiPcsToSck, delayInNanosec, &calculatedDelay); //    /* Set last sck to pcs delay */ //    DSPI_DRV_MasterSetDelay(instance, kDspiLastSckToPcs, delayInNanosec, &calculatedDelay); //    /* Set delay after transfer */ //    DSPI_DRV_MasterSetDelay(instance, kDspiAfterTransfer, delayInNanosec, &calculatedDelay);      /* SPI use interrupt, must be installed in MQX and file fsl_dspi_irq.c must not be included in project */     int32_t IRQNumber = g_dspiIrqId[instance];     _int_install_isr(IRQNumber, (INT_ISR_FPTR)DSPI_DRV_MasterIRQHandler, (void*)instance);      return (kStatus_DSPI_Success); }  int8_t dspicomm_close(uint32_t instance) {     dspi_status_t dspiResult;      dspiResult = DSPI_DRV_MasterDeinit(instance);     if (dspiResult != kStatus_DSPI_Success)     {         printf("\r\nERROR: failure in configuration SPI bus!");         return -1;     }      return (kStatus_DSPI_Success); }  uint32_t dspicomm_read(uint32_t instance, uint8_t *txData, uint32_t txSize, uint8_t *rxData, uint32_t rxSize) {     dspi_status_t     dspiResult;     uint32_t         wordsTransfer = 0;      // Send the data.     dspiResult = DSPI_DRV_MasterTransfer(instance,                                          NULL,                                          txData,                                          rxData,                                          txSize+rxSize);     if (dspiResult != kStatus_DSPI_Success)     {         printf("\r\nERROR: Read data transfer error!");         return (-1);     }     // Wait until the transfer is complete.     while (DSPI_DRV_MasterGetTransferStatus(instance, &wordsTransfer) == kStatus_DSPI_Busy)     {}      return rxSize; }

Outcomes