From 1fe6c2f04a980034a325ada5f8900102b0225a05 Mon Sep 17 00:00:00 2001 From: Mahadevan Mahesh Date: Wed, 17 Aug 2016 08:58:32 -0500 Subject: [PATCH 1/2] KL27Z: Update the SPI driver 1.Fix SPI flag name error 2.Fix SPI write blocking function 3.Use function pointer to implement SPI IRQ handler to reduce code size Signed-off-by: Mahadevan Mahesh --- .../TARGET_KL27Z/drivers/fsl_spi.c | 144 +++++++++++++----- .../TARGET_KL27Z/drivers/fsl_spi.h | 39 +++-- 2 files changed, 127 insertions(+), 56 deletions(-) diff --git a/hal/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_KL27Z/drivers/fsl_spi.c b/hal/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_KL27Z/drivers/fsl_spi.c index 2132fd641c..a7c137618b 100755 --- a/hal/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_KL27Z/drivers/fsl_spi.c +++ b/hal/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_KL27Z/drivers/fsl_spi.c @@ -40,6 +40,9 @@ enum _spi_transfer_states_t kSPI_Busy /*!< SPI is busy tranferring data. */ }; +/*! @brief Typedef for spi master interrupt handler. spi master and slave handle is the same. */ +typedef void (*spi_isr_t)(SPI_Type *base, spi_master_handle_t *spiHandle); + /******************************************************************************* * Prototypes ******************************************************************************/ @@ -92,15 +95,18 @@ static void SPI_ReceiveTransfer(SPI_Type *base, spi_master_handle_t *handle); /******************************************************************************* * Variables ******************************************************************************/ -/* SPI internal handle pointer array */ +/*! @brief SPI internal handle pointer array */ static spi_master_handle_t *s_spiHandle[FSL_FEATURE_SOC_SPI_COUNT]; -/* Base pointer array */ +/*! @brief Base pointer array */ static SPI_Type *const s_spiBases[] = SPI_BASE_PTRS; -/* IRQ name array */ +/*! @brief IRQ name array */ static const IRQn_Type s_spiIRQ[] = SPI_IRQS; -/* Clock array name */ +/*! @brief Clock array name */ static const clock_ip_name_t s_spiClock[] = SPI_CLOCKS; +/*! @brief Pointer to master IRQ handler for each instance. */ +static spi_isr_t s_spiIsr; + /******************************************************************************* * Code ******************************************************************************/ @@ -202,36 +208,64 @@ static void SPI_ReadNonBlocking(SPI_Type *base, uint8_t *buffer, size_t size) static void SPI_SendTransfer(SPI_Type *base, spi_master_handle_t *handle) { uint8_t bytes = MIN((handle->watermark * 2U), handle->txRemainingBytes); - uint8_t val = 1U; /* Read S register and ensure SPTEF is 1, otherwise the write would be ignored. */ if (handle->watermark == 1U) { - val = (base->S & SPI_S_SPTEF_MASK); if (bytes != 0U) { bytes = handle->bytePerFrame; } + + /* Send data */ + if (base->C1 & SPI_C1_MSTR_MASK) + { + /* As a master, only write once */ + if (base->S & SPI_S_SPTEF_MASK) + { + SPI_WriteNonBlocking(base, handle->txData, bytes); + /* Update handle information */ + if (handle->txData) + { + handle->txData += bytes; + } + handle->txRemainingBytes -= bytes; + } } -#if defined(FSL_FEATURE_SPI_HAS_FIFO) && (FSL_FEATURE_SPI_HAS_FIFO) else { - val = (base->S & SPI_S_TNEAREF_MASK); + /* As a slave, send data until SPTEF cleared */ + while ((base->S & SPI_S_SPTEF_MASK) && (handle->txRemainingBytes > 0)) + { + SPI_WriteNonBlocking(base, handle->txData, bytes); + + /* Update handle information */ + if (handle->txData) + { + handle->txData += bytes; + } + handle->txRemainingBytes -= bytes; + } + } + } + +#if defined(FSL_FEATURE_SPI_HAS_FIFO) && (FSL_FEATURE_SPI_HAS_FIFO) + /* If use FIFO */ + else + { + if (base->S & SPI_S_TNEAREF_MASK) + { + SPI_WriteNonBlocking(base, handle->txData, bytes); + + /* Update handle information */ + if (handle->txData) + { + handle->txData += bytes; + } + handle->txRemainingBytes -= bytes; + } } #endif - - /* Write data */ - if (val) - { - SPI_WriteNonBlocking(base, handle->txData, bytes); - - /* Update handle information */ - if (handle->txData) - { - handle->txData += bytes; - } - handle->txRemainingBytes -= bytes; - } } static void SPI_ReceiveTransfer(SPI_Type *base, spi_master_handle_t *handle) @@ -286,6 +320,8 @@ void SPI_MasterGetDefaultConfig(spi_master_config_t *config) void SPI_MasterInit(SPI_Type *base, const spi_master_config_t *config, uint32_t srcClock_Hz) { + assert(config && srcClock_Hz); + /* Open clock gate for SPI and open interrupt */ CLOCK_EnableClock(s_spiClock[SPI_GetInstance(base)]); @@ -345,6 +381,8 @@ void SPI_SlaveGetDefaultConfig(spi_slave_config_t *config) void SPI_SlaveInit(SPI_Type *base, const spi_slave_config_t *config) { + assert(config); + /* Open clock gate for SPI and open interrupt */ CLOCK_EnableClock(s_spiClock[SPI_GetInstance(base)]); @@ -536,6 +574,12 @@ void SPI_MasterSetBaudRate(SPI_Type *base, uint32_t baudRate_Bps, uint32_t srcCl void SPI_WriteBlocking(SPI_Type *base, uint8_t *buffer, size_t size) { uint32_t i = 0; + uint8_t bytesPerFrame = 1U; + +#if defined(FSL_FEATURE_SPI_16BIT_TRANSFERS) && FSL_FEATURE_SPI_16BIT_TRANSFERS + /* Check if 16 bits or 8 bits */ + bytesPerFrame = ((base->C2 & SPI_C2_SPIMODE_MASK) >> SPI_C2_SPIMODE_SHIFT) + 1U; +#endif while (i < size) { @@ -543,14 +587,11 @@ void SPI_WriteBlocking(SPI_Type *base, uint8_t *buffer, size_t size) { } - /* Send data */ - SPI_WriteNonBlocking(base, buffer, size); + /* Send a frame of data */ + SPI_WriteNonBlocking(base, buffer, bytesPerFrame); - /* Wait the data to be sent */ - while ((base->S & SPI_S_SPTEF_MASK) == 0) - { - } - i++; + i += bytesPerFrame; + buffer += bytesPerFrame; } } @@ -668,6 +709,7 @@ void SPI_MasterTransferCreateHandle(SPI_Type *base, s_spiHandle[instance] = handle; handle->callback = callback; handle->userData = userData; + s_spiIsr = SPI_MasterTransferHandleIRQ; #if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO uint8_t txSize = 0U; @@ -836,15 +878,45 @@ void SPI_MasterTransferHandleIRQ(SPI_Type *base, spi_master_handle_t *handle) } } -static void SPI_TransferCommonIRQHandler(SPI_Type *base, void *handle) +void SPI_SlaveTransferCreateHandle(SPI_Type *base, + spi_slave_handle_t *handle, + spi_slave_callback_t callback, + void *userData) { - if (base->C1 & SPI_C1_MSTR_MASK) + assert(handle); + + /* Slave create handle share same logic with master create handle, the only difference + is the Isr pointer. */ + SPI_MasterTransferCreateHandle(base, handle, callback, userData); + s_spiIsr = SPI_SlaveTransferHandleIRQ; +} + +void SPI_SlaveTransferHandleIRQ(SPI_Type *base, spi_slave_handle_t *handle) +{ + assert(handle); + + /* Do data send first in case of data missing. */ + if (handle->txRemainingBytes) { - SPI_MasterTransferHandleIRQ(base, (spi_master_handle_t *)handle); + SPI_SendTransfer(base, handle); } - else + + /* If needs to receive data, do a receive */ + if (handle->rxRemainingBytes) { - SPI_SlaveTransferHandleIRQ(base, (spi_slave_handle_t *)handle); + SPI_ReceiveTransfer(base, handle); + } + + /* All the transfer finished */ + if ((handle->txRemainingBytes == 0) && (handle->rxRemainingBytes == 0)) + { + /* Complete the transfer */ + SPI_SlaveTransferAbort(base, handle); + + if (handle->callback) + { + (handle->callback)(base, handle, kStatus_SPI_Idle, handle->userData); + } } } @@ -852,7 +924,7 @@ static void SPI_TransferCommonIRQHandler(SPI_Type *base, void *handle) void SPI0_DriverIRQHandler(void) { assert(s_spiHandle[0]); - SPI_TransferCommonIRQHandler(SPI0, s_spiHandle[0]); + s_spiIsr(SPI0, s_spiHandle[0]); } #endif @@ -860,7 +932,7 @@ void SPI0_DriverIRQHandler(void) void SPI1_DriverIRQHandler(void) { assert(s_spiHandle[1]); - SPI_TransferCommonIRQHandler(SPI1, s_spiHandle[1]); + s_spiIsr(SPI1, s_spiHandle[1]); } #endif @@ -868,6 +940,6 @@ void SPI1_DriverIRQHandler(void) void SPI2_DriverIRQHandler(void) { assert(s_spiHandle[2]); - SPI_TransferCommonIRQHandler(SPI0, s_spiHandle[2]); + s_spiIsr(SPI0, s_spiHandle[2]); } #endif diff --git a/hal/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_KL27Z/drivers/fsl_spi.h b/hal/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_KL27Z/drivers/fsl_spi.h index 56da5a785a..7e9162350d 100755 --- a/hal/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_KL27Z/drivers/fsl_spi.h +++ b/hal/targets/hal/TARGET_Freescale/TARGET_KSDK2_MCUS/TARGET_KL27Z/drivers/fsl_spi.h @@ -37,7 +37,6 @@ * @{ */ -/*! @file */ /******************************************************************************* * Definitions @@ -45,12 +44,14 @@ /*! @name Driver version */ /*@{*/ -/*! @brief SPI driver version 2.0.0. */ -#define FSL_SPI_DRIVER_VERSION (MAKE_VERSION(2, 0, 0)) +/*! @brief SPI driver version 2.0.1. */ +#define FSL_SPI_DRIVER_VERSION (MAKE_VERSION(2, 0, 1)) /*@}*/ +#ifndef SPI_DUMMYDATA /*! @brief SPI dummy transfer data, the data is sent while txBuff is NULL. */ #define SPI_DUMMYDATA (0xFFU) +#endif /*! @brief Return status for the SPI driver.*/ enum _spi_status @@ -130,10 +131,10 @@ enum _spi_flags #if defined(FSL_FEATURE_SPI_HAS_FIFO) && FSL_FEATURE_SPI_HAS_FIFO kSPI_RxFifoNearFullFlag = SPI_S_RNFULLF_MASK, /*!< Rx FIFO near full */ kSPI_TxFifoNearEmptyFlag = SPI_S_TNEAREF_MASK, /*!< Tx FIFO near empty */ - kSPI_RxFifoFullFlag = SPI_S_TXFULLF_MASK, /*!< Rx FIFO full */ - kSPI_TxFifoEmptyFlag = SPI_S_RFIFOEF_MASK, /*!< Tx FIFO empty */ + kSPI_TxFifoFullFlag = SPI_S_TXFULLF_MASK, /*!< Tx FIFO full */ + kSPI_RxFifoEmptyFlag = SPI_S_RFIFOEF_MASK, /*!< Rx FIFO empty */ kSPI_TxFifoError = SPI_CI_TXFERR_MASK << 8U, /*!< Tx FIFO error */ - kSPI_RxFifoError = SPI_CI_RXFERR_MASK << 8U, /*!< Rx FIFO Overflow */ + kSPI_RxFifoError = SPI_CI_RXFERR_MASK << 8U, /*!< Rx FIFO error */ kSPI_TxOverflow = SPI_CI_TXFOF_MASK << 8U, /*!< Tx FIFO Overflow */ kSPI_RxOverflow = SPI_CI_RXFOF_MASK << 8U /*!< Rx FIFO Overflow */ #endif /* FSL_FEATURE_SPI_HAS_FIFO */ @@ -347,7 +348,7 @@ void SPI_Deinit(SPI_Type *base); * @param base SPI base pointer * @param enable pass true to enable module, false to disable module */ -static inline void SPI_Enable(I2C_Type *base, bool enable) +static inline void SPI_Enable(SPI_Type *base, bool enable) { if (enable) { @@ -581,8 +582,10 @@ status_t SPI_MasterTransferBlocking(SPI_Type *base, spi_transfer_t *xfer); * * @note The API immediately returns after transfer initialization is finished. * Call SPI_GetStatusIRQ() to get the transfer status. - * @note If using the SPI with FIFO for the interrupt transfer, the transfer size is the integer times of the watermark. Otherwise, - * the last data may be lost because it cannot generate an interrupt request. Users can also call the functional API to get the last + * @note If using the SPI with FIFO for the interrupt transfer, the transfer size is the integer times of the watermark. + * Otherwise, + * the last data may be lost because it cannot generate an interrupt request. Users can also call the functional API to + * get the last * received data. * * @param base SPI peripheral base address. @@ -632,21 +635,20 @@ void SPI_MasterTransferHandleIRQ(SPI_Type *base, spi_master_handle_t *handle); * @param callback Callback function. * @param userData User data. */ -static inline void SPI_SlaveTransferCreateHandle(SPI_Type *base, +void SPI_SlaveTransferCreateHandle(SPI_Type *base, spi_slave_handle_t *handle, spi_slave_callback_t callback, - void *userData) -{ - SPI_MasterTransferCreateHandle(base, handle, callback, userData); -} + void *userData); /*! * @brief Performs a non-blocking SPI slave interrupt transfer. * * @note The API returns immediately after the transfer initialization is finished. * Call SPI_GetStatusIRQ() to get the transfer status. - * @note If using the SPI with FIFO for the interrupt transfer, the transfer size is the integer times the watermark. Otherwise, - * the last data may be lost because it cannot generate an interrupt request. Call the functional API to get the last several + * @note If using the SPI with FIFO for the interrupt transfer, the transfer size is the integer times the watermark. + * Otherwise, + * the last data may be lost because it cannot generate an interrupt request. Call the functional API to get the last + * several * receive data. * * @param base SPI peripheral base address. @@ -692,10 +694,7 @@ static inline void SPI_SlaveTransferAbort(SPI_Type *base, spi_slave_handle_t *ha * @param base SPI peripheral base address. * @param handle pointer to spi_slave_handle_t structure which stores the transfer state */ -static inline void SPI_SlaveTransferHandleIRQ(SPI_Type *base, spi_slave_handle_t *handle) -{ - SPI_MasterTransferHandleIRQ(base, handle); -} +void SPI_SlaveTransferHandleIRQ(SPI_Type *base, spi_slave_handle_t *handle); /*! @} */ From 2d97246fb0f52db1bf38fd78b8b34fadc106b93a Mon Sep 17 00:00:00 2001 From: Mahadevan Mahesh Date: Wed, 17 Aug 2016 11:56:25 -0500 Subject: [PATCH 2/2] KL27Z: Update the ARM linker file Signed-off-by: Mahadevan Mahesh --- .../TOOLCHAIN_ARM_STD/MKL27Z64xxx4.sct | 32 ++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/hal/targets/cmsis/TARGET_Freescale/TARGET_KL27Z/TOOLCHAIN_ARM_STD/MKL27Z64xxx4.sct b/hal/targets/cmsis/TARGET_Freescale/TARGET_KL27Z/TOOLCHAIN_ARM_STD/MKL27Z64xxx4.sct index 556bb522b4..a4bb06c9db 100644 --- a/hal/targets/cmsis/TARGET_Freescale/TARGET_KL27Z/TOOLCHAIN_ARM_STD/MKL27Z64xxx4.sct +++ b/hal/targets/cmsis/TARGET_Freescale/TARGET_KL27Z/TOOLCHAIN_ARM_STD/MKL27Z64xxx4.sct @@ -15,7 +15,7 @@ ** Abstract: ** Linker file for the Keil ARM C/C++ Compiler ** -** Copyright (c) 2015 Freescale Semiconductor, Inc. +** Copyright (c) 2016 Freescale Semiconductor, Inc. ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without modification, @@ -50,6 +50,10 @@ */ #define __ram_vector_table__ 1 +/* Heap 1/4 of ram and stack 1/8 */ +#define __stack_size__ 0x800 +#define __heap_size__ 0x1000 + #if (defined(__ram_vector_table__)) #define __ram_vector_table_size__ 0x00000200 #else @@ -71,22 +75,42 @@ #define m_data_start (m_interrupts_ram_start + m_interrupts_ram_size) #define m_data_size (0x00004000 - m_interrupts_ram_size) +/* Sizes */ +#if (defined(__stack_size__)) + #define Stack_Size __stack_size__ +#else + #define Stack_Size 0x0400 +#endif -LR_m_text m_interrupts_start 0x10000 { ; load region size_region +#if (defined(__heap_size__)) + #define Heap_Size __heap_size__ +#else + #define Heap_Size 0x0400 +#endif + +LR_m_text m_interrupts_start m_text_start+m_text_size-m_interrupts_start { ; load region size_region VECTOR_ROM m_interrupts_start m_interrupts_size { ; load address = execution address * (RESET,+FIRST) } ER_m_flash_config m_flash_config_start FIXED m_flash_config_size { ; load address = execution address * (FlashConfig) } - ER_m_text m_text_start FIXED m_text_size { ; load address = execution address + ER_m_text m_text_start m_text_size { ; load address = execution address * (InRoot$$Sections) .ANY (+RO) } + +#if (defined(__ram_vector_table__)) VECTOR_RAM m_interrupts_ram_start EMPTY m_interrupts_ram_size { } - RW_IRAM1 m_data_start m_data_size { ; RW data +#else + VECTOR_RAM m_interrupts_start EMPTY 0 { + } +#endif + RW_m_data m_data_start m_data_size-Stack_Size-Heap_Size { ; RW data .ANY (+RW +ZI) } + RW_IRAM1 +0 EMPTY Heap_Size { ; RW data + } }