From 4e7a7ed4efd1f3174ca9daa14ff75a678f9d1132 Mon Sep 17 00:00:00 2001 From: 1Conan Date: Sun, 29 Jan 2023 23:15:22 +0800 Subject: [PATCH] SN32: Implement SPI LLD --- os/hal/ports/SN32/LLD/SN32F2xx/SPI/SPI.h | 194 --------- os/hal/ports/SN32/LLD/SN32F2xx/SPI/SPI0.c | 138 ------- os/hal/ports/SN32/LLD/SN32F2xx/SPI/SPI1.c | 133 ------ os/hal/ports/SN32/LLD/SN32F2xx/SPI/driver.mk | 8 +- .../SN32/LLD/SN32F2xx/SPI/hal_spi_v2_lld.c | 381 ++++++++++++++++++ .../SN32/LLD/SN32F2xx/SPI/hal_spi_v2_lld.h | 207 ++++++++++ os/hal/ports/SN32/LLD/SN32F2xx/SPI/sn32_spi.h | 99 +++++ os/hal/ports/SN32/SN32F240B/hal_lld.h | 5 + os/hal/ports/SN32/SN32F260/hal_lld.h | 5 + 9 files changed, 704 insertions(+), 466 deletions(-) delete mode 100644 os/hal/ports/SN32/LLD/SN32F2xx/SPI/SPI.h delete mode 100644 os/hal/ports/SN32/LLD/SN32F2xx/SPI/SPI0.c delete mode 100644 os/hal/ports/SN32/LLD/SN32F2xx/SPI/SPI1.c create mode 100644 os/hal/ports/SN32/LLD/SN32F2xx/SPI/hal_spi_v2_lld.c create mode 100644 os/hal/ports/SN32/LLD/SN32F2xx/SPI/hal_spi_v2_lld.h create mode 100644 os/hal/ports/SN32/LLD/SN32F2xx/SPI/sn32_spi.h diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/SPI/SPI.h b/os/hal/ports/SN32/LLD/SN32F2xx/SPI/SPI.h deleted file mode 100644 index 47861e9a5e..0000000000 --- a/os/hal/ports/SN32/LLD/SN32F2xx/SPI/SPI.h +++ /dev/null @@ -1,194 +0,0 @@ -#ifndef __SN32F2XX_SPI_H -#define __SN32F2XX_SPI_H -#include "hal.h" - - -/*_____ I N C L U D E S ____________________________________________________*/ - -/*_____ D E F I N I T I O N S ______________________________________________*/ -/* -Base Address: 0x4001 C000 (SPI0) - -*/ - -/* SPI n Control register 0 (0x00) */ -#define SPI_SPIEN_DIS 0 //[0:0] SPI enable bit -#define SPI_SPIEN_EN 1 -#define mskSPI_SPIEN_DIS (SPI_SPIEN_DIS<<0) -#define mskSPI_SPIEN_EN (SPI_SPIEN_EN<<0) - - //[1:1] Loop back mode disable -#define SPI_LOOPBACK_DIS 0 //Disable -#define SPI_LOOPBACK_EN 1 //Data input from data output -#define mskSPI_LOOPBACK_DIS (SPI_LOOPBACK_DIS<<1) -#define mskSPI_LOOPBACK_EN (SPI_LOOPBACK_EN<<1) - - //[2:2] Slave data output disable bit (ONLY used in slave mode) -#define SPI_SDODIS_EN 0 //Enable slave data output -#define SPI_SDODIS_DIS 1 //Disable slave data output. (MISO=0) -#define mskSPI_SDODIS_EN (SPI_SDODIS_EN<<2) -#define mskSPI_SDODIS_DIS (SPI_SDODIS_DIS<<2) - -#define SPI_MS_MASTER_MODE 0 //[3:3] Master/Slave selection bit -#define SPI_MS_SLAVE_MODE 1 -#define mskSPI_MS_MASTER_MODE (SPI_MS_MASTER_MODE<<3) -#define mskSPI_MS_SLAVE_MODE (SPI_MS_SLAVE_MODE<<3) - - //[7:6] SPI FSM and FIFO Reset bit -#define SPI_FRESET_DO_NOTHING 0 //Do nothing -#define SPI_FRESET_RESET_FIFO 3 //Reset finite state machine and FIFO -#define mskSPI_FRESET_DO_NOTHING (SPI_FRESET_DO_NOTHING<<6) -#define mskSPI_FRESET_RESET_FIFO (SPI_FRESET_RESET_FIFO<<6) - -#define SPI_DL_3 2 //[11:8] Data Length = DL[3:0]+1 -#define SPI_DL_4 3 -#define SPI_DL_5 4 -#define SPI_DL_6 5 -#define SPI_DL_7 6 -#define SPI_DL_8 7 -#define SPI_DL_9 8 -#define SPI_DL_10 9 -#define SPI_DL_11 10 -#define SPI_DL_12 11 -#define SPI_DL_13 12 -#define SPI_DL_14 13 -#define SPI_DL_15 14 -#define SPI_DL_16 15 - -#define SPI_TXFIFOTH_0 0 //[14:12]TX FIFO Threshold level -#define SPI_TXFIFOTH_1 1 -#define SPI_TXFIFOTH_2 2 -#define SPI_TXFIFOTH_3 3 -#define SPI_TXFIFOTH_4 4 -#define SPI_TXFIFOTH_5 5 -#define SPI_TXFIFOTH_6 6 -#define SPI_TXFIFOTH_7 7 - -#define SPI_RXFIFOTH_0 0 //[17:15]RX FIFO Threshold level -#define SPI_RXFIFOTH_1 1 -#define SPI_RXFIFOTH_2 2 -#define SPI_RXFIFOTH_3 3 -#define SPI_RXFIFOTH_4 4 -#define SPI_RXFIFOTH_5 5 -#define SPI_RXFIFOTH_6 6 -#define SPI_RXFIFOTH_7 7 - - //[18:18]Auto-SEL disable bit. For SPI mode only. -#define SPI_SELDIS_EN 0 //Enable Auto-SEL flow control -#define SPI_SELDIS_DIS 1 //Disable Auto-SEL flow control -#define mskSPI_SELDIS_EN (SPI_SELDIS_EN<<18) -#define mskSPI_SELDIS_DIS (SPI_SELDIS_DIS<<18) - - -/* SPI n Control register 1 (0x04) */ - //[0:0]MSB/LSB selection bit -#define SPI_MLSB_MSB 0 //MSB transmit first -#define SPI_MLSB_LSB 1 //LSB transmit first -#define mskSPI_MLSB_MSB (SPI_MLSB_MSB<<0) -#define mskSPI_MLSB_LSB (SPI_MLSB_LSB<<0) - - //[1:1]Clock polarity selection bit -#define SPI_CPOL_SCK_IDLE_LOW 0 //SCK idles at Low level -#define SPI_CPOL_SCK_IDLE_HIGH 1 //SCK idles at High level -#define mskSPI_CPOL_SCK_IDLE_LOW (SPI_CPOL_SCK_IDLE_LOW<<1) -#define mskSPI_CPOL_SCK_IDLE_HIGH (SPI_CPOL_SCK_IDLE_HIGH<<1) - - //[2:2]Clock phase for edge sampling -#define SPI_CPHA_FALLING_EDGE 0 //Data changes at clock falling edge -#define SPI_CPHA_RISING_EDGE 1 //Data changes at clock rising edge -#define mskSPI_CPHA_FALLING_EDGE (SPI_CPHA_FALLING_EDGE<<2) -#define mskSPI_CPHA_RISING_EDGE (SPI_CPHA_RISING_EDGE<<2) - - -/* SPI n Clock Divider register (0x08) */ - //[7:0]SPIn clock divider -#define SPI_DIV 6 //MCLK/n,MCLK=system clk n = 2, 4, 6, 8, ...,512 - - -/* SPI n Status register (0x0C) */ -#define mskSPI_TX_EMPTY (0x1<<0) //TX FIFO empty flag -#define mskSPI_TX_FULL (0x1<<1) //TX FIFO full flag -#define mskSPI_RX_EMPTY (0x1<<2) //RX FIFO empty flag -#define mskSPI_RX_FULL (0x1<<3) //RX FIFO full flag -#define mskSPI_BUSY (0x1<<4) //Busy flag -#define mskSPI_TXFIFOTHF (0x1<<5) //TX FIFO threshold flag -#define mskSPI_RXFIFOTHF (0x1<<6) //RX FIFO threshold flag - - -/* SPI n Interrupt Enable register (0x10) */ -#define SPI_RXOVFIE_DIS 0 //[0:0]RX Overflow interrupt enable -#define SPI_RXOVFIE_EN 1 -#define mskSPI_RXOVFIE_DIS (SPI_RXOVFIE_DIS<<0) -#define mskSPI_RXOVFIE_EN (SPI_RXOVFIE_EN<<0) - -#define SPI_RXTOIE_DIS 0 //[1:1]RX time-out interrupt enable -#define SPI_RXTOIE_EN 1 -#define mskSPI_RXTOIE_DIS (SPI_RXTOIE_DIS<<1) -#define mskSPI_RXTOIE_EN (SPI_RXTOIE_EN<<1) - -#define SPI_RXFIFOTHIE_DIS 0 //[2:2]RX FIFO threshold interrupt enable -#define SPI_RXFIFOTHIE_EN 1 -#define mskSPI_RXFIFOTHIE_DIS (SPI_RXFIFOTHIE_DIS<<2) -#define mskSPI_RXFIFOTHIE_EN (SPI_RXFIFOTHIE_EN <<2) - -#define SPI_TXFIFOTHIE_DIS 0 //[3:3]TX FIFO threshold interrupt enable -#define SPI_TXFIFOTHIE_EN 1 -#define mskSPI_TXFIFOTHIE_DIS (SPI_TXFIFOTHIE_DIS<<3) -#define mskSPI_TXFIFOTHIE_EN (SPI_TXFIFOTHIE_EN<<3) - - -/* SPI n Raw Interrupt Status register (0x14) */ -/* SPI n Interrupt Clear register (0x18) */ -#define mskSPI_RXOVFIF (0x1<<0) //[0:0]RX overflow interrupt flag -#define mskSPI_RXOVFIC mskSPI_RXOVFIF - -#define mskSPI_RXTOIF (0x1<<1) //[1:1]RX time-out interrupt flag -#define mskSPI_RXTOIC mskSPI_RXTOIF - -#define mskSPI_RXFIFOTHIF (0x1<<2) //[2:2]RX FIFO threshold interrupt flag -#define mskSPI_RXFIFOTHIC mskSPI_RXFIFOTHIF - -#define mskSPI_TXFIFOTHIF (0x1<<3) //[3:3]TX FIFO threshold interrupt flag -#define mskSPI_TXFIFOTHIC mskSPI_TXFIFOTHIF - - -/* SPI n Data Fetch register (0x20) */ -//[0:0]SPI data fetch control bit -#define SPI_DF_DIS 0 //Disable -#define SPI_DF_EN 1 //Enable when SCKn frequency > 6MHz -#define mskSPI_DF_DIS (SPI_DF_DIS<<0) -#define mskSPI_SPI_DF_EN (SPI_DF_EN<<0) - - -/*_____ M A C R O S ________________________________________________________*/ -#define __SPI0_FIFO_RESET (SN_SPI0->CTRL0_b.FRESET = SPI_FRESET_RESET_FIFO) -#define __SPI1_FIFO_RESET (SN_SPI1->CTRL0_b.FRESET = SPI_FRESET_RESET_FIFO) -#define __SPI0_CLR_SEL0 (SN_GPIO2->DATA_b.DATA9 = 0) -#define __SPI0_SET_SEL0 (SN_GPIO2->DATA_b.DATA9 = 1) -#define __SPI1_CLR_SEL0 (SN_GPIO2->DATA_b.DATA10 = 0) -#define __SPI1_SET_SEL0 (SN_GPIO2->DATA_b.DATA10 = 1) - -//SPI Data Fetch speed (High: SCK>6MHz) -#if defined(SN32F260) -#define __SPI0_DATA_FETCH_HIGH_SPEED (SN_SPI0->DF = SPI_DF_EN) -#define __SPI1_DATA_FETCH_HIGH_SPEED (SN_SPI1->DF = SPI_DF_EN) -#else -#define __SPI0_DATA_FETCH_HIGH_SPEED (SN_SPI0->DFDLY = SPI_DF_EN) -#define __SPI1_DATA_FETCH_HIGH_SPEED (SN_SPI1->DFDLY = SPI_DF_EN) -#endif - -/*_____ D E C L A R A T I O N S ____________________________________________*/ -extern void SPI0_Init(void); -extern void SPI0_Enable(void); -extern void SPI0_Disable(void); -extern void SPI0_Write1(uint8_t data); -extern void SPI0_Write(uint8_t *data, uint8_t len); -extern void SPI0_Write_End(void); - -extern void SPI1_Init(void); -extern void SPI1_Enable(void); -extern void SPI1_Disable(void); -extern void SPI1_Write1(uint8_t data); -extern void SPI1_Write(uint8_t *data, uint8_t len); -extern void SPI1_Write_End(void); -#endif /*__SN32F2xx_SPI_H*/ diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/SPI/SPI0.c b/os/hal/ports/SN32/LLD/SN32F2xx/SPI/SPI0.c deleted file mode 100644 index cb57523bc7..0000000000 --- a/os/hal/ports/SN32/LLD/SN32F2xx/SPI/SPI0.c +++ /dev/null @@ -1,138 +0,0 @@ -/******************** (C) COPYRIGHT 2014 SONiX ******************************* -* COMPANY: SONiX -* DATE: 2014/05 -* AUTHOR: SA1 -* IC: SN32F240/230/220 -* DESCRIPTION: SPI0 related functions. -*____________________________________________________________________________ -* REVISION Date User Description -* 1.0 2013/12/17 SA1 1. First release -* 1.1 2014/05/23 SA1 1. Add __SSP0_DATA_FETCH_HIGH_SPEED macro -* -*____________________________________________________________________________ -* THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS TIME TO MARKET. -* SONiX SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT OR CONSEQUENTIAL -* DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT OF SUCH SOFTWARE -* AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION CONTAINED HEREIN -* IN CONNECTION WITH THEIR PRODUCTS. -*****************************************************************************/ - -/*_____ I N C L U D E S ____________________________________________________*/ -#include "SPI.h" - - -/*_____ D E C L A R A T I O N S ____________________________________________*/ - - -/*_____ D E F I N I T I O N S ______________________________________________*/ - - -/*_____ M A C R O S ________________________________________________________*/ - - -/*_____ F U N C T I O N S __________________________________________________*/ - -/***************************************************************************** -* Function : SPI0_Init -* Description : Initialization of SPI0 init -* Input : None -* Output : None -* Return : None -* Note : None -*****************************************************************************/ -void SPI0_Init() { - sys1EnableSPI0(); - SN_SPI0->CTRL0_b.DL = SPI_DL_8; - -#ifdef SN32_SPI_SLAVE_MODE - SN_SPI0->CTRL0_b.MS = SPI_MS_SLAVE_MODE; - SN_SPI0->CTRL0_b.SDODIS = SPI_SDODIS_EN; -#else - SN_SPI0->CTRL0_b.MS = SPI_MS_MASTER_MODE; -#endif - - SN_SPI0->CTRL0_b.LOOPBACK = SPI_LOOPBACK_DIS; - -#ifdef SN32_SPI_RXFIFO_THRESHOLD - SN_SPI0->CTRL0_b.RXFIFOTH = SN32_SPI_TXFIFO_THRESHOLD; -#endif - -#ifdef SN32_SPI_TXFIFO_THRESHOLD - SN_SPI0->CTRL0_b.TXFIFOTH = SN32_SPI_TXFIFO_THRESHOLD; -#endif - -#ifdef SN32_SPI_CLKDIV - SN_SPI0->CLKDIV_b.DIV = SN32_SPI_CLKDIV; -#else - SN_SPI0->CLKDIV_b.DIV = (SPI_DIV / 2) - 1; -#endif - - SN_SPI0->CTRL1_b.CPHA = SPI_CPHA_FALLING_EDGE; - SN_SPI0->CTRL1_b.CPOL = SPI_CPOL_SCK_IDLE_LOW; - SN_SPI0->CTRL1_b.MLSB = SPI_MLSB_MSB; - -#ifdef SN32_SPI_AUTOSEL - SN_SPI0->CTRL0_b.SELDIS = SN32_SPI_AUTOSEL; -#endif - - __SPI0_FIFO_RESET; - - uint32_t spiClock = (SN32_HCLK / ((2 * SN_SPI0->CLKDIV_b.DIV) + 2)); - if (spiClock > 6000000) { - __SPI0_DATA_FETCH_HIGH_SPEED; - } - - NVIC_DisableIRQ(SN32_SPI0_NUMBER); -} - -/***************************************************************************** -* Function : SPI0_Enable -* Description : SPI0 enable setting -* Input : None -* Output : None -* Return : None -* Note : None -*****************************************************************************/ -void SPI0_Enable() { - sys1EnableSPI0(); -#if defined(SN32F260) - SN_SPI0->CTRL0_b.SSPEN = SPI_SPIEN_EN; -#else - SN_SPI0->CTRL0_b.SPIEN = SPI_SPIEN_EN; -#endif - __SPI0_FIFO_RESET; -} - -/***************************************************************************** -* Function : SPI0_Disable -* Description : SPI0 disable setting -* Input : None -* Output : None -* Return : None -* Note : None -*****************************************************************************/ -void SPI0_Disable() { -#if defined(SN32F260) - SN_SPI0->CTRL0_b.SSPEN = SPI_SPIEN_DIS; -#else - SN_SPI0->CTRL0_b.SPIEN = SPI_SPIEN_DIS; -#endif - //Disable HCLK for SSP0 - sys1DisableSPI0(); -} - -void SPI0_Write1(uint8_t data) { - while (SN_SPI0->STAT_b.TX_FULL); - SN_SPI0->DATA = data; -} - -void SPI0_Write(uint8_t *data, uint8_t len) { - for (uint8_t i = 0; i < len; i++) { - SPI0_Write1(data[i]); - } -} - -void SPI0_Write_End() { - while (!SN_SPI0->STAT_b.TX_EMPTY); -} diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/SPI/SPI1.c b/os/hal/ports/SN32/LLD/SN32F2xx/SPI/SPI1.c deleted file mode 100644 index 8253a9b4c2..0000000000 --- a/os/hal/ports/SN32/LLD/SN32F2xx/SPI/SPI1.c +++ /dev/null @@ -1,133 +0,0 @@ -/******************** (C) COPYRIGHT 2014 SONiX ******************************* -* COMPANY: SONiX -* DATE: 2014/05 -* AUTHOR: SA1 -* IC: SN32F240/230/220 -* DESCRIPTION: SPI1 related functions. -*____________________________________________________________________________ -* REVISION Date User Description -* 1.0 2013/12/17 SA1 1. First release -* 1.1 2014/05/23 SA1 1. Add __SSP1_DATA_FETCH_HIGH_SPEED macro -* -*____________________________________________________________________________ -* THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS -* WITH CODING INFORMATION REGARDING THEIR PRODUCTS TIME TO MARKET. -* SONiX SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT OR CONSEQUENTIAL -* DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT OF SUCH SOFTWARE -* AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION CONTAINED HEREIN -* IN CONNECTION WITH THEIR PRODUCTS. -*****************************************************************************/ - -/*_____ I N C L U D E S ____________________________________________________*/ -#include "SPI.h" - - -/*_____ D E C L A R A T I O N S ____________________________________________*/ - - -/*_____ D E F I N I T I O N S ______________________________________________*/ - - -/*_____ M A C R O S ________________________________________________________*/ - - -/*_____ F U N C T I O N S __________________________________________________*/ - -/***************************************************************************** -* Function : SPI1_Init -* Description : Initialization of SPI1 init -* Input : None -* Output : None -* Return : None -* Note : None -*****************************************************************************/ -void SPI1_Init() { - sys1EnableSPI1(); - SN_SPI1->CTRL0_b.DL = SPI_DL_8; - -#ifdef SN32_SPI_SLAVE_MODE - SN_SPI1->CTRL0_b.MS = SPI_MS_SLAVE_MODE; - SN_SPI1->CTRL0_b.SDODIS = SPI_SDODIS_EN; -#else - SN_SPI1->CTRL0_b.MS = SPI_MS_MASTER_MODE; -#endif - - SN_SPI1->CTRL0_b.LOOPBACK = SPI_LOOPBACK_DIS; - -#ifdef SN32_SPI_RXFIFO_THRESHOLD - SN_SPI1->CTRL0_b.RXFIFOTH = SN32_SPI_TXFIFO_THRESHOLD; -#endif - -#ifdef SN32_SPI_TXFIFO_THRESHOLD - SN_SPI1->CTRL0_b.TXFIFOTH = SN32_SPI_TXFIFO_THRESHOLD; -#endif - -#ifdef SN32_SPI_CLKDIV - SN_SPI1->CLKDIV_b.DIV = SN32_SPI_CLKDIV; -#else - SN_SPI1->CLKDIV_b.DIV = (SPI_DIV / 2) - 1; -#endif - - SN_SPI1->CTRL1_b.CPHA = SPI_CPHA_FALLING_EDGE; - SN_SPI1->CTRL1_b.CPOL = SPI_CPOL_SCK_IDLE_LOW; - SN_SPI1->CTRL1_b.MLSB = SPI_MLSB_MSB; - -#ifdef SN32_SPI_AUTOSEL - SN_SPI1->CTRL0_b.SELDIS = SN32_SPI_AUTOSEL; -#endif - - __SPI1_FIFO_RESET; - - uint32_t spiClock = (SN32_HCLK / ((2 * SN_SPI1->CLKDIV_b.DIV) + 2)); - if (spiClock > 6000000) { - __SPI1_DATA_FETCH_HIGH_SPEED; - } - - NVIC_DisableIRQ(SN32_SPI1_NUMBER); -} - -/***************************************************************************** -* Function : SPI1_Enable -* Description : SPI1 enable setting -* Input : None -* Output : None -* Return : None -* Note : None -*****************************************************************************/ -void SPI1_Enable() { - sys1EnableSPI1(); - - SN_SPI1->CTRL0_b.SPIEN = SPI_SPIEN_EN; - - __SPI1_FIFO_RESET; -} - -/***************************************************************************** -* Function : SPI1_Disable -* Description : SPI1 disable setting -* Input : None -* Output : None -* Return : None -* Note : None -*****************************************************************************/ -void SPI1_Disable() { - SN_SPI1->CTRL0_b.SPIEN = SPI_SPIEN_DIS; - - //Disable HCLK for SSP1 - sys1DisableSPI1(); -} - -void SPI1_Write1(uint8_t data) { - while (SN_SPI1->STAT_b.TX_FULL); - SN_SPI1->DATA = data; -} - -void SPI1_Write(uint8_t *data, uint8_t len) { - for (uint8_t i = 0; i < len; i++) { - SPI1_Write1(data[i]); - } -} - -void SPI1_Write_End() { - while (!SN_SPI1->STAT_b.TX_EMPTY); -} diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/SPI/driver.mk b/os/hal/ports/SN32/LLD/SN32F2xx/SPI/driver.mk index a36e42a575..dc2b5d0467 100644 --- a/os/hal/ports/SN32/LLD/SN32F2xx/SPI/driver.mk +++ b/os/hal/ports/SN32/LLD/SN32F2xx/SPI/driver.mk @@ -1,3 +1,9 @@ -PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/SN32/LLD/SN32F2xx/SPI/SPI0.c +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_SPI TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/SN32/LLD/SN32F2xx/SPI/hal_pal_v2_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/SN32/LLD/SN32F2xx/SPI/hal_spi_v2_lld.c +endif PLATFORMINC += $(CHIBIOS_CONTRIB)/os/hal/ports/SN32/LLD/SN32F2xx/SPI diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/SPI/hal_spi_v2_lld.c b/os/hal/ports/SN32/LLD/SN32F2xx/SPI/hal_spi_v2_lld.c new file mode 100644 index 0000000000..38dc6d98af --- /dev/null +++ b/os/hal/ports/SN32/LLD/SN32F2xx/SPI/hal_spi_v2_lld.c @@ -0,0 +1,381 @@ +/* + ChibiOS - Copyright (C) 2023 1Conan + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file hal_spi_v2_lld.c + * @brief SN32 SPI (v2) subsystem low level driver source. + * + * @addtogroup SPI_V2 + * @{ + */ + +#include "hal.h" + +#if HAL_USE_SPI || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief SPI0 driver identifier. + */ +#if (SN32_SPI_USE_SPI0 == TRUE) || defined(__DOXYGEN__) +SPIDriver SPID0; +#endif + +/** + * @brief SPI1 driver identifier. + */ +#if (SN32_SPI_USE_SPI1 == TRUE) || defined(__DOXYGEN__) +SPIDriver SPID1; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +static void spi_lld_configure(SPIDriver *spip) { + spip->spi->CTRL0 = spip->config->ctrl0; + spip->spi->CTRL1 = spip->config->ctrl1; + spip->spi->CLKDIV = spip->config->clkdiv; + + spip->spi->CTRL0 |= (spip->config->slave << 3); + spip->spi->CTRL0_b.SDODIS = false; + +#if SPI_SELECT_MODE == SPI_SELECT_MODE_LLD + // Use hardware Auto-SEL + spip->spi->CTRL0_b.SELDIS = false; +#endif + + uint32_t sn32_spi_clock = (SN32_HCLK / ((2 * spip->config->clkdiv) + 2)); + if (sn32_spi_clock > 6000000) { + spip->spi->DFDLY = true; + } + + SPI_FIFO_FRESET(spip); + + spip->spi->IC = 0b1111; + // enable RX FIFO threshold interrupt + spip->spi->IE = 0b0100; + + spip->spi->CTRL0_b.SPIEN = true; +} + +static inline void spi_lld_irq_handler(SPIDriver *spip) { + if (spip->spi->RIS_b.RXFIFOTHIF) { + chSysLockFromISR(); + uint16_t data = spip->spi->DATA; + spip->spi->IC_b.RXFIFOTHIC = true; + chSysUnlockFromISR(); + + if (spip->rxbuf) spip->rxbuf[spip->idx] = data; + + if (++(spip->idx) >= spip->count) { + __spi_isr_complete_code(spip); + } else { + spip->spi->DATA = spip->txbuf ? spip->txbuf[spip->idx] : 0x00; + } + } +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if SN32_SPI_USE_SPI0 +OSAL_IRQ_HANDLER(SN32_SPI0_HANDLER) { + OSAL_IRQ_PROLOGUE(); + + spi_lld_irq_handler(&SPID0); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +#if SN32_SPI_USE_SPI1 +OSAL_IRQ_HANDLER(SN32_SPI1_HANDLER) { + OSAL_IRQ_PROLOGUE(); + + spi_lld_irq_handler(&SPID1); + + OSAL_IRQ_EPILOGUE(); +} +#endif + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level SPI driver initialization. + * + * @notapi + */ +void spi_lld_init(void) { + +#if SN32_SPI_USE_SPI0 == TRUE + /* Driver initialization.*/ + spiObjectInit(&SPID0); + SPID0.spi = SN32_SPI0; +#endif + +#if SN32_SPI_USE_SPI1 == TRUE + /* Driver initialization.*/ + spiObjectInit(&SPID1); + SPID1.spi = SN32_SPI1; +#endif +} + +/** + * @brief Configures and activates the SPI peripheral. + * + * @param[in] spip pointer to the @p SPIDriver object + * @return The operation status. + * + * @notapi + */ +msg_t spi_lld_start(SPIDriver *spip) { + + if (spip->state == SPI_STOP) { + + /* Enables the peripheral.*/ + +#if SN32_SPI_USE_SPI0 == TRUE + if (&SPID0 == spip) { + sys1EnableSPI0(); + nvicClearPending(SN32_SPI0_NUMBER); + nvicEnableVector(SN32_SPI0_NUMBER, SN32_SPI_SPI0_IRQ_PRIORITY); + } +#endif + +#if SN32_SPI_USE_SPI1 == TRUE + if (&SPID1 == spip) { + sys1EnableSPI1(); + nvicClearPending(SN32_SPI1_NUMBER); + nvicEnableVector(SN32_SPI1_NUMBER, SN32_SPI_SPI1_IRQ_PRIORITY); + } +#endif + + else { + osalDbgAssert(false, "invalid SPI instance"); + } + } + + spi_lld_configure(spip); + + return HAL_RET_SUCCESS; +} + +/** + * @brief Deactivates the SPI peripheral. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @notapi + */ +void spi_lld_stop(SPIDriver *spip) { + + if (spip->state == SPI_READY) { + + /* Disables the peripheral.*/ + + SPI_FIFO_FRESET(spip); + + spip->spi->CTRL0_b.SPIEN = false; + +#if SN32_SPI_USE_SPI0 == TRUE + if (&SPID0 == spip) { + sys1DisableSPI0(); + nvicDisableVector(SN32_SPI0_NUMBER); + } +#endif + +#if SN32_SPI_USE_SPI1 == TRUE + if (&SPID1 == spip) { + sys1DisableSPI1(); + nvicDisableVector(SN32_SPI1_NUMBER); + } +#endif + + else { + osalDbgAssert(false, "invalid SPI instance"); + } + } +} + +#if (SPI_SELECT_MODE == SPI_SELECT_MODE_LLD) || defined(__DOXYGEN__) +/** + * @brief Asserts the slave select signal and prepares for transfers. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @notapi + */ +void spi_lld_select(SPIDriver *spip) { + + (void)spip; + // noop - hardware auto-sel +} + +/** + * @brief Deasserts the slave select signal. + * @details The previously selected peripheral is unselected. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @notapi + */ +void spi_lld_unselect(SPIDriver *spip) { + + (void)spip; + // noop - hardware auto-sel +} +#endif + +/** + * @brief Ignores data on the SPI bus. + * @details This synchronous function performs the transmission of a series of + * idle words on the SPI bus and ignores the received data. + * @pre In order to use this function the option @p SPI_USE_SYNCHRONIZATION + * must be enabled. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to be ignored + * @return The operation status. + * + * @notapi + */ +msg_t spi_lld_ignore(SPIDriver *spip, size_t n) { + return spi_lld_exchange(spip, n, NULL, NULL); +} + +/** + * @brief Exchanges data on the SPI bus. + * @details This asynchronous function starts a simultaneous transmit/receive + * operation. + * @post At the end of the operation the configured callback is invoked. + * @note The buffers are organized as uint8_t arrays for data sizes below or + * equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to be exchanged + * @param[in] txbuf the pointer to the transmit buffer + * @param[out] rxbuf the pointer to the receive buffer + * @return The operation status. + * + * @notapi + */ +msg_t spi_lld_exchange(SPIDriver *spip, size_t n, + const void *txbuf, void *rxbuf) { + + spip->txbuf = txbuf; + spip->rxbuf = rxbuf; + spip->count = n; + spip->idx = 0; + + spip->spi->DATA = spip->txbuf ? spip->txbuf[0] : 0x00; + + return HAL_RET_SUCCESS; +} + +/** + * @brief Sends data over the SPI bus. + * @details This asynchronous function starts a transmit operation. + * @post At the end of the operation the configured callback is invoked. + * @note The buffers are organized as uint8_t arrays for data sizes below or + * equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to send + * @param[in] txbuf the pointer to the transmit buffer + * @return The operation status. + * + * @notapi + */ +msg_t spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) { + return spi_lld_exchange(spip, n, txbuf, NULL); +} + +/** + * @brief Receives data from the SPI bus. + * @details This asynchronous function starts a receive operation. + * @post At the end of the operation the configured callback is invoked. + * @note The buffers are organized as uint8_t arrays for data sizes below or + * equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to receive + * @param[out] rxbuf the pointer to the receive buffer + * @return The operation status. + * + * @notapi + */ +msg_t spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) { + return spi_lld_exchange(spip, n, NULL, rxbuf); +} + +/** + * @brief Aborts the ongoing SPI operation, if any. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[out] sizep pointer to the counter of frames not yet transferred + * or @p NULL + * @return The operation status. + * + * @notapi + */ +msg_t spi_lld_stop_transfer(SPIDriver *spip, size_t *sizep) { + + SPI_FIFO_FRESET(spip); + + if (sizep != NULL) { + *sizep = spip->count - spip->idx; + } + + return HAL_RET_SUCCESS; +} + +/** + * @brief Exchanges one frame using a polled wait. + * @details This synchronous function exchanges one frame using a polled + * synchronization method. This function is useful when exchanging + * small amount of data on high speed channels, usually in this + * situation is much more efficient just wait for completion using + * polling than suspending the thread waiting for an interrupt. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] frame the data frame to send over the SPI bus + * @return The received data frame from the SPI bus. + */ +uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame) { + spip->spi->DATA = frame; + while (spip->spi->STAT_b.RX_EMPTY); + + return spip->spi->DATA; +} + +#endif /* HAL_USE_SPI */ + +/** @} */ diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/SPI/hal_spi_v2_lld.h b/os/hal/ports/SN32/LLD/SN32F2xx/SPI/hal_spi_v2_lld.h new file mode 100644 index 0000000000..0a6ed33a91 --- /dev/null +++ b/os/hal/ports/SN32/LLD/SN32F2xx/SPI/hal_spi_v2_lld.h @@ -0,0 +1,207 @@ +/* + ChibiOS - Copyright (C) 2023 1Conan + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file hal_spi_v2_lld.h + * @brief SN32 SPI (v2) subsystem low level driver header. + * + * @addtogroup SPI_V2 + * @{ + */ + +#ifndef HAL_SPI_V2_LLD_H +#define HAL_SPI_V2_LLD_H + +#if HAL_USE_SPI || defined(__DOXYGEN__) + +#include "sn32_spi.h" + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Circular mode support flag. + */ +#define SPI_SUPPORTS_CIRCULAR FALSE + +/** + * @brief Slave mode support flag. + */ +#define SPI_SUPPORTS_SLAVE_MODE TRUE + +/** @defgroup SPI_Exported_Constants + * @{ + */ + +/** @defgroup SPI_SN32_CTRL0 + * @{ + */ +#define SPI_DATA_LENGTH(x) ((x - 1) << 8) +#define SPI_TXFIFO_LENGTH(x) (x << 12) +#define SPI_RXFIFO_LENGTH(x) (x << 15) +#define SPI_LOOPBACK_ENABLE (1 << 1) +/** + * @} + */ + +/** @defgroup SPI_SN32_CTRL1 + * @{ + */ +#define SPI_MLSB_MSB (0 << 0) +#define SPI_MLSB_LSB (1 << 0) +#define SPI_CPOL_LOW (0 << 1) +#define SPI_CPOL_HIGH (1 << 1) +#define SPI_CPHA_FALLING (0 << 2) +#define SPI_CPHA_RISING (1 << 2) +/** + * @} + */ + +/** + * @} + */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name SN32 configuration options + * @{ + */ +/** + * @brief SPI0 driver enable switch. + * @details If set to @p TRUE the support for SPI1 is included. + * @note The default is @p FALSE. + */ +#if !defined(SN32_SPI_USE_SPI0) || defined(__DOXYGEN__) +#define SN32_SPI_USE_SPI0 FALSE +#endif + +/* + * @brief SPI1 driver enable switch. + * @details If set to @p TRUE the support for SPI1 is included. + * @note The default is @p FALSE. + */ +#if !defined(SN32_SPI_USE_SPI1) || defined(__DOXYGEN__) +#define SN32_SPI_USE_SPI1 FALSE +#endif + +/** + * @brief SPI0 interrupt priority level setting. + */ +#if !defined(SN32_SPI_SPI0_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define SN32_SPI_SPI0_IRQ_PRIORITY 3 +#endif + +/** + * @brief SPI1 interrupt priority level setting. + */ +#if !defined(SN32_SPI_SPI1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define SN32_SPI_SPI1_IRQ_PRIORITY 3 +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if SN32_SPI_USE_SPI0 && !SN32_HAS_SPI0 +#error "SPI0 not present in the selected device" +#endif + +#if SN32_SPI_USE_SPI1 && !SN32_HAS_SPI1 +#error "SPI1 not present in the selected device" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +#if SN32_HAS_SPI0 +#define SN32_SPI0_BASE SN_SPI0_BASE +#define SN32_SPI0 ((sn32_spi_t *)SN_SPI0_BASE) +#endif + +#if SN32_HAS_SPI1 +#define SN32_SPI1_BASE SN_SPI1_BASE +#define SN32_SPI1 ((sn32_spi_t *)SN_SPI1_BASE) +#endif + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +#define SPI_FIFO_FRESET(spip) (spip->spi->CTRL0_b.FRESET = 0b11) + +/** + * @brief Low level fields of the SPI driver structure. + */ +#define spi_lld_driver_fields \ + sn32_spi_t *spi; \ + uint8_t *rxbuf; \ + const uint8_t *txbuf; \ + uint32_t count; \ + uint32_t idx; + +/** + * @brief Low level fields of the SPI configuration structure. + */ +#define spi_lld_config_fields \ + uint32_t ctrl0; \ + uint32_t ctrl1; \ + uint32_t clkdiv; + + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if (SN32_SPI_USE_SPI0 == TRUE) && !defined(__DOXYGEN__) +extern SPIDriver SPID0; +#endif + +#if (SN32_SPI_USE_SPI1 == TRUE) && !defined(__DOXYGEN__) +extern SPIDriver SPID1; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void spi_lld_init(void); + msg_t spi_lld_start(SPIDriver *spip); + void spi_lld_stop(SPIDriver *spip); +#if (SPI_SELECT_MODE == SPI_SELECT_MODE_LLD) || defined(__DOXYGEN__) + void spi_lld_select(SPIDriver *spip); + void spi_lld_unselect(SPIDriver *spip); +#endif + msg_t spi_lld_ignore(SPIDriver *spip, size_t n); + msg_t spi_lld_exchange(SPIDriver *spip, size_t n, + const void *txbuf, void *rxbuf); + msg_t spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf); + msg_t spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf); + msg_t spi_lld_stop_transfer(SPIDriver *spip, size_t *sizep); + uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_SPI */ + +#endif /* HAL_SPI_V2_LLD_H */ + +/** @} */ diff --git a/os/hal/ports/SN32/LLD/SN32F2xx/SPI/sn32_spi.h b/os/hal/ports/SN32/LLD/SN32F2xx/SPI/sn32_spi.h new file mode 100644 index 0000000000..4395c40b9d --- /dev/null +++ b/os/hal/ports/SN32/LLD/SN32F2xx/SPI/sn32_spi.h @@ -0,0 +1,99 @@ +/* + ChibiOS - Copyright (C) 2023 1Conan + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#ifndef SN32_SPI_H +#define SN32_SPI_H + +typedef struct { + union { + uint32_t CTRL0; + struct { + uint32_t SPIEN : 1; + uint32_t LOOPBACK : 1; + uint32_t SDODIS : 1; + uint32_t MS : 1; + uint32_t FORMAT : 1; + uint32_t : 1; + uint32_t FRESET : 2; + uint32_t DL : 4; + uint32_t TXFIFOTH : 3; + uint32_t RXFIFOTH : 3; + uint32_t SELDIS : 1; + uint32_t : 13; + } CTRL0_b; + }; + + uint32_t CTRL1; + uint32_t CLKDIV; + + union { + uint32_t STAT; + + struct { + uint32_t TX_EMPTY : 1; + uint32_t TX_FULL : 1; + uint32_t RX_EMPTY : 1; + uint32_t RX_FULL : 1; + uint32_t BUSY : 1; + uint32_t TXFIFOTHF : 1; + uint32_t RXFIFOTHF : 1; + uint32_t : 25; + } STAT_b; + }; + + union { + uint32_t IE; + + struct { + uint32_t RXOVFIE : 1; + uint32_t RXTOIE : 1; + uint32_t RXFIFOTHIE : 1; + uint32_t TXFIFOTHIE : 1; + uint32_t : 28; + } IE_b; + }; + + union { + uint32_t RIS; + + struct { + uint32_t RXOVFIF : 1; + uint32_t RXTOIF : 1; + uint32_t RXFIFOTHIF : 1; + uint32_t TXFIFOTHIF : 1; + uint32_t : 28; + } RIS_b; + }; + + union { + uint32_t IC; + + struct { + uint32_t RXOVFIC : 1; + uint32_t RXTOIC : 1; + uint32_t RXFIFOTHIC : 1; + uint32_t TXFIFOTHIC : 1; + uint32_t : 28; + } IC_b; + }; + + uint32_t DATA; + uint32_t DFDLY; +} sn32_spi_t; + +#endif /* SN32_SPI_H */ + +/** @} */ diff --git a/os/hal/ports/SN32/SN32F240B/hal_lld.h b/os/hal/ports/SN32/SN32F240B/hal_lld.h index 68a4c40718..77d8d08fa7 100644 --- a/os/hal/ports/SN32/SN32F240B/hal_lld.h +++ b/os/hal/ports/SN32/SN32F240B/hal_lld.h @@ -38,6 +38,11 @@ #define PLATFORM_NAME "SN32F24xB" /** @} */ +/** + * @brief Requires use of SPIv2 driver model. + */ +#define HAL_LLD_SELECT_SPI_V2 TRUE + /*===========================================================================*/ /* Driver pre-compile time settings. */ /*===========================================================================*/ diff --git a/os/hal/ports/SN32/SN32F260/hal_lld.h b/os/hal/ports/SN32/SN32F260/hal_lld.h index b182d1c247..74f6fe477f 100644 --- a/os/hal/ports/SN32/SN32F260/hal_lld.h +++ b/os/hal/ports/SN32/SN32F260/hal_lld.h @@ -38,6 +38,11 @@ #define PLATFORM_NAME "SN32F26x" /** @} */ +/** + * @brief Requires use of SPIv2 driver model. + */ +#define HAL_LLD_SELECT_SPI_V2 TRUE + /*===========================================================================*/ /* Driver pre-compile time settings. */ /*===========================================================================*/