EFM32 Happy Gecko Software Documentation  efm32hg-doc-5.1.2
ksz8851snl_spi.c
Go to the documentation of this file.
1 /**************************************************************************/
15 #include <stdio.h>
16 #include <stdint.h>
17 
18 #include "ksz8851snl_spi.h"
19 #include "em_assert.h"
20 #include "em_common.h"
21 #include "em_gpio.h"
22 #include "spidrv.h"
23 
24 #define BOGUS_BYTE 0xFF
25 #define REG_MASK 0x03
26 #define OPCODE_REG_READ 0x00
27 #define OPCODE_REG_WRITE 0x40
28 #define OPCODE_FIFO_READ 0x80
29 #define OPCODE_FIFO_WRITE 0xC0
30 #define ADDRESS_MS2B_POS 0x06
31 #define ADDRESS_SHIFT 0x02
32 #define BYTE_ENABLE 0x03
33 #define BYTE_ENABLE_SHIFT 0x02
35 /* GPIO pins used for SPI communication. */
36 /*(USART 1, Location #1) */
37 #define ETH_CS_PIN 3
38 #define ETH_CS_PORT gpioPortD
42 static SPIDRV_HandleData_t spiHandleData;
43 static SPIDRV_Handle_t spiHandle = &spiHandleData;
44 
48 /**************************************************************************/
58 {
59  Ecode_t result;
61  initData.bitRate = 8000000; // 8 MHz max safe speed
62  initData.frameLength = 8;
63  initData.dummyTxValue = BOGUS_BYTE;
65  initData.clockMode = spidrvClockMode0;
67 
68  result = SPIDRV_Init(spiHandle, &initData);
69  EFM_ASSERT(result == ECODE_EMDRV_SPIDRV_OK);
70 
72 }
73 
74 
75 /**************************************************************************/
85 static void KSZ8851SNL_SPI_Transmit(int numBytes, const uint8_t * data)
86 {
87  Ecode_t result;
88  int remaining = numBytes;
89 
90  /* The spidrv is using dma to transfer bytes to the USART (spi)
91  * this is why we must transmit bytes in chunks of at most
92  * DMADRV_MAX_XFER_COUNT (1024 on EFM32GG990F1024)
93  */
94  do {
95  int count = SL_MIN(remaining, DMADRV_MAX_XFER_COUNT);
96  result = SPIDRV_MTransmitB(spiHandle, data, count);
97  remaining -= count;
98  data += count;
99  } while (result == ECODE_EMDRV_SPIDRV_OK && remaining > 0);
100 
101  EFM_ASSERT(result == ECODE_EMDRV_SPIDRV_OK);
102 }
103 
104 
105 /**************************************************************************/
115 static void KSZ8851SNL_SPI_Receive(int numBytes, uint8_t * buffer)
116 {
117  Ecode_t result;
118  int remaining = numBytes;
119 
120  /* The spidrv is using dma to receive bytes from the USART (spi)
121  * this is why we must receive bytes in chunks of at most
122  * DMADRV_MAX_XFER_COUNT (1024 on EFM32GG990F1024)
123  */
124  do {
125  int count = SL_MIN(remaining, DMADRV_MAX_XFER_COUNT);
126  result = SPIDRV_MReceiveB(spiHandle, buffer, count);
127  remaining -= count;
128  buffer += count;
129  } while (result == ECODE_EMDRV_SPIDRV_OK && remaining > 0);
130 
131  EFM_ASSERT(result == ECODE_EMDRV_SPIDRV_OK);
132 }
133 
134 
135 /**************************************************************************/
144 static void KSZ8851SNL_SPI_SetChipSelect(bool enable)
145 {
146  if (enable)
147  {
149  }
150  else
151  {
153  }
154 }
155 
156 
157 /**************************************************************************/
167 uint16_t KSZ8851SNL_SPI_ReadRegister(uint8_t reg)
168 {
169  uint16_t value = 0x0000;
170  uint8_t txBuffer[4];
171  uint8_t rxBuffer[4];
172 
185  txBuffer[0] = OPCODE_REG_READ;
186  txBuffer[0] |= BYTE_ENABLE << (BYTE_ENABLE_SHIFT + (reg & REG_MASK));
187  txBuffer[0] |= (reg >> ADDRESS_MS2B_POS);
188  txBuffer[1] = (reg << ADDRESS_SHIFT) & 0xf0;
189 
191  SPIDRV_MTransferB(spiHandle, txBuffer, rxBuffer, 4);
193 
194  value = (rxBuffer[3] << 8) | rxBuffer[2];
195  return value;
196 }
197 
198 
199 /**************************************************************************/
209 void KSZ8851SNL_SPI_WriteRegister(uint8_t reg, uint16_t value)
210 {
211  uint8_t txBuffer[4];
212 
225  txBuffer[0] = OPCODE_REG_WRITE | (BYTE_ENABLE << (BYTE_ENABLE_SHIFT + (reg & REG_MASK)));
226  txBuffer[0] |= reg >> ADDRESS_MS2B_POS;
227  txBuffer[1] = (reg << ADDRESS_SHIFT) & 0xf0;
228  txBuffer[2] = value & 0xff;
229  txBuffer[3] = (value >> 8) & 0xff;
230 
232  KSZ8851SNL_SPI_Transmit(4, txBuffer);
234 }
235 
236 
237 /*************************************************************************/
257 void KSZ8851SNL_SPI_ReadFifo(int numBytes, uint8_t *data)
258 {
259  EFM_ASSERT(numBytes >= 0 && numBytes < 12000);
260  EFM_ASSERT(data != NULL);
261 
262  uint8_t cmd = OPCODE_FIFO_READ;
263  uint8_t dummy[4];
264 
266  KSZ8851SNL_SPI_Transmit(1, &cmd);
267  KSZ8851SNL_SPI_Receive(4, dummy);
268  KSZ8851SNL_SPI_Receive(numBytes, data);
270 }
271 
272 /*************************************************************************/
276 {
277  uint8_t cmd = OPCODE_FIFO_WRITE;
278  /* Enable chip select */
280  /* Send Write command */
281  KSZ8851SNL_SPI_Transmit(1, &cmd);
282 }
283 
284 /*************************************************************************/
289 void KSZ8851SNL_SPI_WriteFifo(int numBytes, const uint8_t *data)
290 {
291  EFM_ASSERT(numBytes >= 0 && numBytes < 12000);
292  EFM_ASSERT(data != NULL);
293 
294  KSZ8851SNL_SPI_Transmit(numBytes, data);
295 }
296 
297 
298 /*************************************************************************/
302 {
304 }
SPI interface API for KSZ8851SNL Ethernet controller.
Emlib peripheral API "assert" implementation.
SPIDRV API definition.
Ecode_t SPIDRV_MTransmitB(SPIDRV_Handle_t handle, const void *buffer, int count)
Start a SPI master blocking transmit transfer.
Definition: spidrv.c:843
uint32_t dummyTxValue
The value to transmit when using SPI receive API functions.
Definition: spidrv.h:136
MSB bit is transmitted first.
Definition: spidrv.h:65
SPIDRV_BitOrder_t bitOrder
Bit order on SPI bus, MSB or LSB first.
Definition: spidrv.h:138
Ecode_t SPIDRV_MTransferB(SPIDRV_Handle_t handle, const void *txBuffer, void *rxBuffer, int count)
Start a SPI master blocking transfer.
Definition: spidrv.c:694
static void KSZ8851SNL_SPI_Transmit(int numBytes, const uint8_t *data)
Transmits a series of bytes over the spi link.
#define OPCODE_REG_READ
General purpose utilities.
static void KSZ8851SNL_SPI_Receive(int numBytes, uint8_t *buffer)
Receive a series of bytes over the spi link.
uint32_t bitRate
SPI bitrate.
Definition: spidrv.h:134
void KSZ8851SNL_SPI_WriteFifo(int numBytes, const uint8_t *data)
Continue writing ethernet controller FIFO.
#define ECODE_EMDRV_SPIDRV_OK
Success return value.
Definition: spidrv.h:43
#define REG_MASK
uint16_t KSZ8851SNL_SPI_ReadRegister(uint8_t reg)
Read ethernet controller register.
void GPIO_PinModeSet(GPIO_Port_TypeDef port, unsigned int pin, GPIO_Mode_TypeDef mode, unsigned int out)
Set the mode for a GPIO pin.
Definition: em_gpio.c:269
General Purpose IO (GPIO) peripheral API.
#define OPCODE_FIFO_WRITE
void KSZ8851SNL_SPI_WriteFifoEnd(void)
Stop read/write the ethernet controller FIFO.
uint32_t Ecode_t
Typedef for API function error code return values.
Definition: ecode.h:51
#define BYTE_ENABLE_SHIFT
#define DMADRV_MAX_XFER_COUNT
Maximum length of one DMA transfer.
Definition: dmadrv.h:87
__STATIC_INLINE void GPIO_PinOutSet(GPIO_Port_TypeDef port, unsigned int pin)
Set a single pin in GPIO data out register to 1.
Definition: em_gpio.h:856
#define ADDRESS_SHIFT
void KSZ8851SNL_SPI_ReadFifo(int numBytes, uint8_t *data)
Read data from the ethernet controller RX FIFO.
#define ETH_CS_PORT
#define ETH_CS_PIN
CS controlled by application.
Definition: spidrv.h:81
static volatile uint8_t rxBuffer[RXBUFSIZE]
SPI mode 0: CLKPOL=0, CLKPHA=0.
Definition: spidrv.h:71
void KSZ8851SNL_SPI_Init(void)
KSZ8851SNL_SPI_Init Initialize SPI interface to Ethernet controller.
Ecode_t SPIDRV_Init(SPIDRV_Handle_t handle, SPIDRV_Init_t *initData)
Initialize a SPI driver instance.
Definition: spidrv.c:101
#define ADDRESS_MS2B_POS
#define SL_MIN(a, b)
Macro for getting minimum value. No sideeffects, a and b are evaluated once only. ...
Definition: em_common.h:137
#define BYTE_ENABLE
void KSZ8851SNL_SPI_WriteRegister(uint8_t reg, uint16_t value)
Write ethernet controller register.
__STATIC_INLINE void GPIO_PinOutClear(GPIO_Port_TypeDef port, unsigned int pin)
Set a single pin in GPIO data out port register to 0.
Definition: em_gpio.h:811
#define SPIDRV_MASTER_USART1
Configuration data for SPI master using USART1.
Definition: spidrv.h:436
#define OPCODE_REG_WRITE
static void KSZ8851SNL_SPI_SetChipSelect(bool enable)
Select/deselect the ksz8851snl chip. This will clear/set the chip select GPIO pin connected to the ks...
uint32_t frameLength
SPI framelength, valid numbers are 4..16.
Definition: spidrv.h:135
void KSZ8851SNL_SPI_WriteFifoBegin(void)
Start writing to the ethernet controller FIFO.
SPIDRV_CsControl_t csControl
Select master mode chip select (CS) control scheme.
Definition: spidrv.h:140
SPIDRV_ClockMode_t clockMode
SPI mode, CLKPOL/CLKPHASE setting.
Definition: spidrv.h:139
Ecode_t SPIDRV_MReceiveB(SPIDRV_Handle_t handle, void *buffer, int count)
Start a SPI master blocking receive transfer.
Definition: spidrv.c:602
#define BOGUS_BYTE
#define OPCODE_FIFO_READ