/***************************************************************** ****************************************************************** ** ** ** MODULE W5500_SPI1.c ** ** ABSTRACT SPI Driver read/write ** ** ** ****************************************************************** ******************************************************************/ #include #define NOP1 asm volatile ( "nop" "\n" ); #define W5500_CS_Pin LL_GPIO_PIN_4 #define W5500_CS_GPIO_Port GPIOA #define W5500_IRQ_Pin LL_GPIO_PIN_2 #define W5500_IRQ_GPIO_Port GPIOB #define W5500_CS_LOW LL_GPIO_ResetOutputPin (W5500_CS_GPIO_Port, W5500_CS_Pin); #define W5500_CS_HIGH LL_GPIO_SetOutputPin (W5500_CS_GPIO_Port, W5500_CS_Pin); // W5500 Data Modes #define OM10_VDM 00 /* variable data mode */ #define OM10_FDM1 01 /* fixed data mode, 1 byte */ #define OM10_FDM2 10 /* fixed data mode, 2 byte */ #define OM10_FDM3 11 /* fixed data mode, 4 byte */ static uint32_t current_mode = 0xAA55; /* SPI mode */ static uint32_t oldspeed = 11111ul; /* speed value */ /* FUNCTION ************************************/ void MX_SPI1_Init_xx(void) { LL_SPI_InitTypeDef SPI_InitStruct = {0}; LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; /* ------------------------ */ /* SPI CS1: PA4 */ /* ------------------------ */ LL_AHB1_GRP1_EnableClock (LL_AHB1_GRP1_PERIPH_GPIOA); LL_GPIO_ResetOutputPin (W5500_CS_GPIO_Port, W5500_CS_Pin); GPIO_InitStruct.Pin = W5500_CS_Pin; GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT; GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; LL_GPIO_Init (W5500_CS_GPIO_Port, &GPIO_InitStruct); /* ------------------------ */ /* W5500 IRQ: PB2 */ /* ------------------------ */ LL_AHB1_GRP1_EnableClock (LL_AHB1_GRP1_PERIPH_GPIOB); LL_GPIO_ResetOutputPin (W5500_IRQ_GPIO_Port, W5500_IRQ_Pin); GPIO_InitStruct.Pin = W5500_IRQ_Pin; GPIO_InitStruct.Mode = LL_GPIO_MODE_INPUT; GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; GPIO_InitStruct.Pull = LL_GPIO_PULL_UP; LL_GPIO_Init (W5500_IRQ_GPIO_Port, &GPIO_InitStruct); /* Peripheral clock enable */ LL_APB2_GRP1_EnableClock (LL_APB2_GRP1_PERIPH_SPI1); LL_AHB1_GRP1_EnableClock (LL_AHB1_GRP1_PERIPH_GPIOA); /* ------------------------ */ /* SPI1 GPIO Configuration PA5 ------> SPI1_SCK PA6 ------> SPI1_MISO PA7 ------> SPI1_MOSI */ /* ------------------------ */ GPIO_InitStruct.Pin = LL_GPIO_PIN_5 | LL_GPIO_PIN_6 | LL_GPIO_PIN_7; GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE; GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; GPIO_InitStruct.Alternate = LL_GPIO_AF_5; LL_GPIO_Init (GPIOA, &GPIO_InitStruct); SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX; SPI_InitStruct.Mode = LL_SPI_MODE_MASTER; SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_8BIT; SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_LOW; SPI_InitStruct.ClockPhase = LL_SPI_PHASE_1EDGE; SPI_InitStruct.NSS = LL_SPI_NSS_SOFT; SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV2; SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST; SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE; SPI_InitStruct.CRCPoly = 10; LL_SPI_Init (SPI1, &SPI_InitStruct); LL_SPI_SetStandard (SPI1, LL_SPI_PROTOCOL_MOTOROLA); LL_SPI_Enable (SPI1); SPI1_SetSpeed (6000000ul); // 6 MHz } /* --- MX_SPI1_Init --- */ /* FUNCTION ************************************/ void SPI1_SetMode (uint16_t mode) /* * SPECIFICATION: * PARAMETERS: * SIDE_EFFECTS: * RETURN VALUES: ***********************************************/ { uint16_t temp_reg; if (current_mode != mode) { /* temporarily disable the selected SPI peripheral */ SPI1->CR1 &= (uint16_t)~((uint16_t)SPI_CR1_SPE); temp_reg = SPI1->CR1; /* Clear bits */ temp_reg &= ~(LL_SPI_PHASE_2EDGE | LL_SPI_POLARITY_LOW); if (mode == SPI_MODE_0) { temp_reg |= (LL_SPI_POLARITY_LOW | LL_SPI_PHASE_1EDGE); } else if (mode == SPI_MODE_1) { temp_reg |= (LL_SPI_POLARITY_LOW | LL_SPI_PHASE_2EDGE); } else if (mode == SPI_MODE_2) { temp_reg |= (LL_SPI_POLARITY_HIGH | LL_SPI_PHASE_1EDGE); } else if (mode == SPI_MODE_3) { temp_reg |= (LL_SPI_POLARITY_HIGH | LL_SPI_PHASE_2EDGE); } SPI1->CR1 = temp_reg; /* Write to SPIx CR1 */ current_mode = mode; /* re-enable the selected SPI peripheral */ SPI1->CR1 |= SPI_CR1_SPE; } } /* --- SPI1_SetMode --- */ /* FUNCTION ************************************/ void W5500_CS_Low (void) { W5500_CS_LOW; } /* --- W5500_CS_Low --- */ /* FUNCTION ************************************/ void W5500_CS_High (void) { W5500_CS_HIGH; } /* --- W5500_CS_High --- */ /* FUNCTION ************************************/ uint16_t W5500_Get_IRQ (void) /* * SPECIFICATION: * PARAMETERS: * SIDE_EFFECTS: * RETURN VALUES: ***********************************************/ { if ( ( (W5500_IRQ_GPIO_Port->IDR) & W5500_IRQ_Pin) != 0) return 1; else return 0; } /* --- W5500_Get_IRQ --- */ /* FUNCTION ************************************/ uint8_t SPI1_Transfer (uint8_t val) /* * SPECIFICATION: * PARAMETERS: * SIDE_EFFECTS: * RETURN VALUES: ***********************************************/ { uint8_t rd_val; W5500_CS_LOW; while ((SPI1->SR & LL_SPI_SR_TXE) == 0) { /* wait */ }; SPI1->DR = (uint8_t)(val); /* wait for RX not empty */ while ((SPI1->SR & LL_SPI_SR_RXNE) == 0) { /* wait */ }; rd_val = SPI1->DR; /* wait for Busy flag not active */ while ((SPI1->SR & LL_SPI_SR_BSY) != 0); W5500_CS_HIGH; return rd_val; } /* --- SPI1_Transfer --- */ /* FUNCTION ************************************/ //uint16_t spi_transfer (uint16_t val) inline __attribute__((__always_inline__)) uint16_t spi_transfer (uint16_t val) { SPI1->DR = val; while ((SPI1->SR & LL_SPI_SR_TXE ) == 0) { /* wait */ }; //while ((SPI1->SR & SPI_I2S_FLAG_RXNE) == 0) { /* wait */ }; while ((SPI1->SR & LL_SPI_SR_BSY) != 0) { /* wait */ }; return SPI1->DR; } /* --- spi_transfer --- */ /* FUNCTION ************************************/ uint8_t W5500_spi_read (uint32_t addr) /* * Single byte read from W5500 register ***********************************************/ { #define OPMODE_SINGLE_READ (0x00 | OM10_FDM1) // BSB = %00000, RW=0(read), OM =%00 uint8_t rd_val; W5500_CS_LOW; // CS=0, SPI start spi_transfer ( (uint8_t)(addr >> 16) ); spi_transfer ( (uint8_t)(addr >> 8) ); spi_transfer ( ((uint8_t)addr) | OPMODE_SINGLE_READ); rd_val = spi_transfer (0); W5500_CS_HIGH; // CS=1, SPI end return rd_val; } /* --- W5500_spi_read --- */ /* FUNCTION ************************************/ void W5500_spi_write (uint32_t addr, uint8_t val) /* * Single byte write to W5500 register ***********************************************/ { #define OPMODE_SINGLE_WRITE (0x04 | OM10_FDM1) // BSB = %00000, RW=1(write), OM =%00 W5500_CS_LOW; // CS=0, SPI start while ((SPI1->SR & LL_SPI_SR_TXE) == 0) { /* wait */ }; SPI1->DR = (uint8_t)(addr >> 16); while ((SPI1->SR & LL_SPI_SR_TXE) == 0) { /* wait */ }; SPI1->DR = (uint8_t)(addr >> 8); while ((SPI1->SR & LL_SPI_SR_TXE) == 0) { /* wait */ }; SPI1->DR = ((uint8_t)addr | OPMODE_SINGLE_WRITE); while ((SPI1->SR & LL_SPI_SR_TXE) == 0) { /* wait */ }; SPI1->DR = val; /* data write */ while ((SPI1->SR & SPI_SR_BSY) != 0); W5500_CS_HIGH; // CS=1, SPI end } /* --- W5500_spi_write --- */ /* FUNCTION ************************************/ void W5500_spi_read_buf (uint32_t addr, uint8_t* p_buf, uint16_t numbytes) /* * read from W5500 memory (Buffer) * ***********************************************/ { #define OPMODE_READ (0x00 | OM10_VDM) // BSB = %00000, RW=0(read), OM =%00 W5500_CS_LOW; // CS=0, SPI start spi_transfer(addr >> 16); spi_transfer(addr >> 8); spi_transfer((uint8_t)addr | OPMODE_READ); while (numbytes > 0) { *p_buf = spi_transfer(0); p_buf++; numbytes--; } W5500_CS_HIGH; // CS=1, SPI end } /* --- W5500_spi_read_buf --- */ /* FUNCTION ************************************/ void W5500_spi_write_buf (uint32_t addr, uint8_t* p_buf, uint16_t numbytes) /* * write into W5500 memory (Buffer) * ***********************************************/ { #define OPMODE_WRITE (0x04 | OM10_VDM) // BSB = %00000, RW=1(write), OM =%00 W5500_CS_LOW; // CS=0, SPI start while ((SPI1->SR & LL_SPI_SR_TXE) == 0) { /* wait */ }; SPI1->DR = (uint8_t)(addr >> 16); while ((SPI1->SR & LL_SPI_SR_TXE) == 0) { /* wait */ }; SPI1->DR = (uint8_t)(addr >> 8); while ((SPI1->SR & LL_SPI_SR_TXE) == 0) { /* wait */ }; SPI1->DR = ((uint8_t)addr | OPMODE_WRITE); while (numbytes > 0) { while ((SPI1->SR & LL_SPI_SR_TXE) == 0) { /* wait */ }; SPI1->DR = *p_buf; p_buf++; numbytes--; } /* wait for Busy flag not active */ while ((SPI1->SR & SPI_SR_BSY) != 0); W5500_CS_HIGH; // CS=1, SPI end } /* --- W5500_spi_write_buf --- */ /* ------------------------------------------ */ /* -------- End of file W5500_SPI1.c -------- */ /* ------------------------------------------ */