NXP

S32K144 + FreeRTOS + SPI + IAR

2019-07-12 12:57发布

开发环境:IAR 8.30 FreeRTOS版本:10.1  
  • 一、移植FreeRTOS
  • 二、配置IAR
  • 三、配置IO、使能DMA、SPI
  • 四、创建任务、开启任务调度

一、移植FreeRTOS

  1. 从官网下载FreeRTOS源码
  2. 将..FreeRTOS_v10_1_0Source目录下的FreeRTOS源码复制到工程目录下
  3. 将..FreeRTOS_v10_1_0SourceportableIARARM_CM4F下的文件添加到工程目录下
  4. 将..FreeRTOS_v10_1_0SourceportableMemMang下的一种内存管理文件添加到工程目录下
  5. 打开S32DS下FreeRTOS例程的文件夹,复制其中的FreeRTOSConfig.h到工程目录下
  6. 复制S32DS中的连接文件以及脚本文件
  

二、配置IAR

 三、配置IO、使能DMA、SPI

配置IO        PINS_DRV_Init(NUM_OF_CONFIGURED_PINS, g_pin_mux_InitConfigArr); 使能DMA #define EDMA_CHN0_NUMBER 0U #define EDMA_CHN1_NUMBER 1U #define EDMA_CHN2_NUMBER 2U #define EDMA_CHN3_NUMBER 3U #define EDMA_CONFIGURED_CHANNELS_COUNT 4U edma_state_t dmaController1_State; edma_chn_state_t dmaController1Chn0_State; edma_chn_state_t dmaController1Chn1_State; edma_chn_state_t dmaController1Chn2_State; edma_chn_state_t dmaController1Chn3_State; edma_chn_state_t * const edmaChnStateArray[] = { &dmaController1Chn0_State, &dmaController1Chn1_State, &dmaController1Chn2_State, &dmaController1Chn3_State }; void SPI_EDMA_init(void) { edma_channel_config_t dmaController1Chn0_Config = { .channelPriority = EDMA_CHN_DEFAULT_PRIORITY, .virtChnConfig = EDMA_CHN0_NUMBER, .source = EDMA_REQ_LPSPI0_RX, .callback = NULL, .callbackParam = NULL }; edma_channel_config_t dmaController1Chn1_Config = { .channelPriority = EDMA_CHN_DEFAULT_PRIORITY, .virtChnConfig = EDMA_CHN1_NUMBER, .source = EDMA_REQ_LPSPI0_TX, .callback = NULL, .callbackParam = NULL }; edma_channel_config_t dmaController1Chn2_Config = { .channelPriority = EDMA_CHN_DEFAULT_PRIORITY, .virtChnConfig = EDMA_CHN2_NUMBER, .source = EDMA_REQ_LPSPI1_RX, .callback = NULL, .callbackParam = NULL }; edma_channel_config_t dmaController1Chn3_Config = { .channelPriority = EDMA_CHN_DEFAULT_PRIORITY, .virtChnConfig = EDMA_CHN3_NUMBER, .source = EDMA_REQ_LPSPI1_TX, .callback = NULL, .callbackParam = NULL }; const edma_channel_config_t * const edmaChnConfigArray[] = { &dmaController1Chn0_Config, &dmaController1Chn1_Config, &dmaController1Chn2_Config, &dmaController1Chn3_Config }; const edma_user_config_t dmaController1_InitConfig0 = { .chnArbitration = EDMA_ARBITRATION_FIXED_PRIORITY, .notHaltOnError = false, }; EDMA_DRV_Init(&dmaController1_State, &dmaController1_InitConfig0, edmaChnStateArray, edmaChnConfigArray, EDMA_CONFIGURED_CHANNELS_COUNT); } 初始化Master--SPI lpspi_state_t SendState; void SPIMasterInit(void) { uint32_t ret = 0; const lpspi_master_config_t Send_MasterConfig0 = { .bitsPerSec = 10000000U, .whichPcs = LPSPI_PCS0, .pcsPolarity = LPSPI_ACTIVE_HIGH, .isPcsContinuous = false, .bitcount = 8U, .lpspiSrcClk = 48000000U, .clkPhase = LPSPI_CLOCK_PHASE_1ST_EDGE, .clkPolarity = LPSPI_SCK_ACTIVE_HIGH, .lsbFirst = false, .transferType = LPSPI_USING_DMA, .rxDMAChannel = 0U, .txDMAChannel = 1U, .callback = NULL, .callbackParam = NULL, }; /* SPI master configuration: clock speed: 500 kHz, 8 bits/frame, MSB first */ ret = LPSPI_DRV_MasterInit(0, &SendState, &Send_MasterConfig0); printf(" SPI Master Init : 0x%x ", ret); /* Configure delay between transfer, delay between SCK and PCS and delay between PCS and SCK */ LPSPI_DRV_MasterSetDelay(0, 1, 1, 1); } 初始化Slave--SPI lpspi_state_t ReceiveState; void SPISlaveInit(void) { uint32_t ret = 0; const lpspi_slave_config_t Receive_SlaveConfig0 = { .pcsPolarity = LPSPI_ACTIVE_HIGH, .bitcount = 8U, .clkPhase = LPSPI_CLOCK_PHASE_1ST_EDGE, .whichPcs = LPSPI_PCS0, .clkPolarity = LPSPI_SCK_ACTIVE_HIGH, .lsbFirst = false, .transferType = LPSPI_USING_DMA, .rxDMAChannel = 2U, .txDMAChannel = 3U, .callback = NULL, .callbackParam = NULL, }; ret = LPSPI_DRV_SlaveInit(0, &ReceiveState, &Receive_SlaveConfig0); printf(" SPI SlaveInit : 0x%x ", ret); }

四、创建任务、开启任务调度

特别注意:     1、关于systick:由于FreeRTOS中的时间片调度已经使能设置了systick,故不必在设置     2、设置中断的组别:NVIC_SetPriorityGrouping(0x3);     3、由于FreeRTOS的中断优先级较低,会影响到正常的信号量的获取等,故需在程序刚开始时调用INT_SYS_SetPriority();修改系统中所有中断的优先级 创建任务     xTaskCreate((TaskFunction_t )IPC_task,               //任务函数                  (const char*    )"IPC_task",             //任务名称                 (uint16_t       )IPC_TASK_STK_SIZE,      //任务堆栈大小                 (void*          )NULL,                   //传递给任务函数的参数                 (UBaseType_t    )IPC_TASK_STK_PRIO,  //任务优先级                        (TaskHandle_t*  )&IPC_Task_Handler);     //任务句柄         vTaskStartScheduler();                               //开启任务调度 Master--SPI任务函数 void IPC_task(void *pvParameters) {     uint8_t TXBuffer[10] = {0,1,2,3,4,5,6,7,8,9};     uint8_t RXBuffer[10] = {0};          while(1)     {         LPSPI_DRV_MasterTransferBlocking(0, TXBuffer, RXBuffer, sizeof(TXBuffer), 10U);         printf(" Master recever 0x%x 0x%x 0x%x 0x%x ", RXBuffer[0], RXBuffer[1], RXBuffer[2], RXBuffer[3]);         vTaskDelay(1000);     } } Slave--SPI任务函数 void IPC_task(void *pvParameters) {     uint8_t TXBuffer[10] = {9,8,7,6,5,4,3,2,1,0};     uint8_t RXBuffer[10] = {0};          while(1)     {         LPSPI_DRV_SlaveTransfer(0, TXBuffer, RXBuffer, sizeof(RXBuffer), 10U);         printf(" Master recever 0x%x 0x%x 0x%x 0x%x ", RXBuffer[0], RXBuffer[1], RXBuffer[2], RXBuffer[3]);         vTaskDelay(1000);     } }