123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237 |
- /*
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- */
- #include "LPC17xx.h" /* LPC17xx definitions */
- #include "spi.h"
- /* bit definitions for register SSPCR0. */
- #define SSPCR0_DSS 0
- #define SSPCR0_CPOL 6
- #define SSPCR0_CPHA 7
- #define SSPCR0_SCR 8
- /* bit definitions for register SSPCR1. */
- #define SSPCR1_SSE 1
- /* bit definitions for register SSPSR. */
- #define SSPSR_TFE 0
- #define SSPSR_TNF 1
- #define SSPSR_RNE 2
- #define SSPSR_RFF 3
- #define SSPSR_BSY 4
- /* Local functions */
- static uint8_t LPC17xx_SPI_SendRecvByte (uint8_t byte_s);
- /* Initialize the SSP0, SSP0_PCLK=CCLK=72MHz */
- void LPC17xx_SPI_Init (void)
- {
- uint32_t dummy;
- dummy = dummy; // avoid warning
- #if 0
- /* Initialize and enable the SSP0 Interface module. */
- LPC_SC->PCONP |= (1 << 21); /* Enable power to SSPI0 block */
- /* SSEL is GPIO, output set to high. */
- LPC_GPIO0->FIODIR |= (1<<16); /* P0.16 is output */
- LPC_PINCON->PINSEL1 &= ~(3<<0); /* P0.16 SSEL (used as GPIO) */
- LPC17xx_SPI_DeSelect (); /* set P0.16 high (SSEL inactiv) */
- /* SCK, MISO, MOSI are SSP pins. */
- LPC_PINCON->PINSEL0 &= ~(3UL<<30); /* P0.15 cleared */
- LPC_PINCON->PINSEL0 |= (2UL<<30); /* P0.15 SCK0 */
- LPC_PINCON->PINSEL1 &= ~((3<<2) | (3<<4)); /* P0.17, P0.18 cleared */
- LPC_PINCON->PINSEL1 |= ((2<<2) | (2<<4)); /* P0.17 MISO0, P0.18 MOSI0 */
- #else
- LPC_SC->PCONP |= (1 << 21); /* Enable power to SSPI0 block */
- /* SSEL is GPIO, output set to high. */
- LPC_GPIO1->FIODIR |= (1<<21); /* P1.21 is output */
- LPC_GPIO1->FIOPIN |= (1<<21); /* set P1.21 high (SSEL inact.)*/
- LPC_PINCON->PINSEL3 &= ~(0<<10); /* P1.21 SSEL (used as GPIO) */
- /* P3.26 is SD Card Power Supply Enable Pin */
- LPC_GPIO3->FIODIR |= (1<<26); /* P3.26 is output */
- LPC_GPIO3->FIOPIN &= ~(1<<26); /* set P3.26 low(enable power) */
- /* SCK, MISO, MOSI are SSP pins. */
- LPC_PINCON->PINSEL3 &= ~(3UL<<8); /* P1.20 cleared */
- LPC_PINCON->PINSEL3 |= (3UL<<8); /* P1.20 SCK0 */
- LPC_PINCON->PINSEL3 &= ~((3<<14) | (3<<16)); /* P1.23, P1.24 cleared */
- LPC_PINCON->PINSEL3 |= ((3<<14) | (3<<16)); /* P1.23 MISO0, P1.24 MOSI0 */
- #endif
- /* PCLK_SSP0=CCLK */
- LPC_SC->PCLKSEL1 &= ~(3<<10); /* PCLKSP0 = CCLK/4 (18MHz) */
- LPC_SC->PCLKSEL1 |= (1<<10); /* PCLKSP0 = CCLK (72MHz) */
- LPC_SSP0->CR0 = 0x0007; /* 8Bit, CPOL=0, CPHA=0 */
- LPC_SSP0->CR1 = 0x0002; /* SSP0 enable, master */
- LPC17xx_SPI_SetSpeed (SPI_SPEED_400kHz);
- /* wait for busy gone */
- while( LPC_SSP0->SR & ( 1 << SSPSR_BSY ) );
- /* drain SPI RX FIFO */
- while( LPC_SSP0->SR & ( 1 << SSPSR_RNE ) )
- {
- dummy = LPC_SSP0->DR;
- }
- }
- /* Close SSP0 */
- void LPC17xx_SPI_DeInit( void )
- {
- // disable SPI
- LPC_SSP0->CR1 = 0;
- #if 0
- // Pins to GPIO
- LPC_PINCON->PINSEL0 &= ~(3UL<<30);
- LPC_PINCON->PINSEL1 &= ~((3<<2) | (3<<4));
- #else
- LPC_PINCON->PINSEL3 &= ~(3UL<<8); /* P1.20 cleared */
- LPC_PINCON->PINSEL3 &= ~((3<<14) | (3<<16)); /* P1.23, P1.24 cleared */
- #endif
- // disable SSP power
- LPC_SC->PCONP &= ~(1 << 21);
- }
- /* Set a SSP0 clock speed to desired value. */
- void LPC17xx_SPI_SetSpeed (uint8_t speed)
- {
- speed &= 0xFE;
- if ( speed < 2 ) {
- speed = 2 ;
- }
- LPC_SSP0->CPSR = speed;
- }
- /* SSEL: low */
- void LPC17xx_SPI_Select ()
- {
- #if 0
- LPC_GPIO0->FIOPIN &= ~(1<<16);
- #else
- LPC_GPIO1->FIOPIN &= ~(1<<21); /* SSEL is GPIO, set to high. */
- #endif
- }
- /* SSEL: high */
- void LPC17xx_SPI_DeSelect ()
- {
- #if 0
- LPC_GPIO0->FIOPIN |= (1<<16);
- #else
- LPC_GPIO1->FIOPIN |= (1<<21); /* SSEL is GPIO, set to high. */
- #endif
- }
- /* Send one byte then recv one byte of response. */
- static uint8_t LPC17xx_SPI_SendRecvByte (uint8_t byte_s)
- {
- uint8_t byte_r;
- LPC_SSP0->DR = byte_s;
- while (LPC_SSP0->SR & (1 << SSPSR_BSY) /*BSY*/); /* Wait for transfer to finish */
- byte_r = LPC_SSP0->DR;
- return byte_r; /* Return received value */
- }
- /* Send one byte */
- void LPC17xx_SPI_SendByte (uint8_t data)
- {
- LPC17xx_SPI_SendRecvByte (data);
- }
- /* Recv one byte */
- uint8_t LPC17xx_SPI_RecvByte ()
- {
- return LPC17xx_SPI_SendRecvByte (0xFF);
- }
- /* Release SSP0 */
- void LPC17xx_SPI_Release (void)
- {
- LPC17xx_SPI_DeSelect ();
- LPC17xx_SPI_RecvByte ();
- }
- #if USE_FIFO
- /* on LPC17xx the FIFOs have 8 elements which each can hold up to 16 bits */
- #define FIFO_ELEM 8
- /* Receive btr (must be multiple of 4) bytes of data and store in buff. */
- void LPC17xx_SPI_RecvBlock_FIFO (uint8_t *buff, uint32_t btr)
- {
- uint32_t hwtr, startcnt, i, rec;
- hwtr = btr/2; /* byte number in unit of short */
- if ( btr < FIFO_ELEM ) {
- startcnt = hwtr;
- } else {
- startcnt = FIFO_ELEM;
- }
- LPC_SSP0 -> CR0 |= 0x0f; /* DSS to 16 bit */
- for ( i = startcnt; i; i-- ) {
- LPC_SSP0 -> DR = 0xffff; /* fill TX FIFO, prepare clk for receive */
- }
- do {
- while ( !(LPC_SSP0->SR & ( 1 << SSPSR_RNE ) ) ) {
- // wait for data in RX FIFO (RNE set)
- }
- rec = LPC_SSP0->DR;
- if ( i < ( hwtr - startcnt ) ) {
- LPC_SSP0->DR = 0xffff; /* fill TX FIFO, prepare clk for receive */
- }
- *buff++ = (uint8_t)(rec>>8);
- *buff++ = (uint8_t)(rec);
- i++;
- } while ( i < hwtr );
- LPC_SSP0->CR0 &= ~0x08; /* DSS to 8 bit */
- }
- /* Send 512 bytes of data block (stored in buff). */
- void LPC17xx_SPI_SendBlock_FIFO (const uint8_t *buff)
- {
- uint32_t cnt;
- uint16_t data;
- LPC_SSP0->CR0 |= 0x0f; /* DSS to 16 bit */
- /* fill the FIFO unless it is full */
- for ( cnt = 0; cnt < ( 512 / 2 ); cnt++ )
- {
- /* wait for TX FIFO not full (TNF) */
- while ( !( LPC_SSP0->SR & ( 1 << SSPSR_TNF ) ) );
- data = (*buff++) << 8;
- data |= *buff++;
- LPC_SSP0->DR = data;
- }
- /* wait for BSY gone */
- while ( LPC_SSP0->SR & ( 1 << SSPSR_BSY ) );
- /* drain receive FIFO */
- while ( LPC_SSP0->SR & ( 1 << SSPSR_RNE ) ) {
- data = LPC_SSP0->DR;
- }
- LPC_SSP0->CR0 &= ~0x08; /* DSS to 8 bit */
- }
- #endif /* USE_FIFO */
|