///////////////////////////////////////////////////////////////////////////// // This hook is called after startup to initialize the application ///////////////////////////////////////////////////////////////////////////// void APP_Init(void) { // initialize all LEDs MIOS32_BOARD_LED_Init(0xffffffff); // initialize SPI interface // ensure that fast pin drivers are activated MIOS32_SPI_IO_Init(SLAVE_SPI, MIOS32_SPI_PIN_SLAVE_DRIVER_STRONG); // init SPI port MIOS32_SPI_TransferModeInit(SLAVE_SPI, MIOS32_SPI_MODE_SLAVE_CLK1_PHASE1, MIOS32_SPI_PRESCALER_128); // start task xTaskCreate(TASK_SPI_Handler, (signed portCHAR *)"SPI_Handler", configMINIMAL_STACK_SIZE, NULL, PRIORITY_TASK_SPI_HANDLER, NULL); }
///////////////////////////////////////////////////////////////////////////// //! Connects to ENC28J60 chip //! \return < 0 if initialisation sequence failed //! \return -16 if clock not ready after system reset //! \return -17 if unsupported revision ID ///////////////////////////////////////////////////////////////////////////// s32 MIOS32_ENC28J60_PowerOn(void) { s32 status; // deactivate chip select CSN_1; // ensure that fast pin drivers are activated MIOS32_SPI_IO_Init(MIOS32_ENC28J60_SPI, MIOS32_SPI_PIN_DRIVER_STRONG); // init SPI port for fast frequency access (ca. 18 MBit/s) if( (status=MIOS32_SPI_TransferModeInit(MIOS32_ENC28J60_SPI, MIOS32_SPI_MODE_CLK0_PHASE0, MIOS32_SPI_PRESCALER_4)) < 0 ) return status; // send system reset command // RESET the entire ENC28J60, clearing all registers // Also wait for CLKRDY to become set. // Bit 3 in ESTAT is an unimplemented bit. If it reads out as '1' that // means the part is in RESET or there is something wrong with the SPI // connection. This routine makes sure that we can communicate with the // ENC28J60 before proceeding. if( (status=MIOS32_ENC28J60_SendSystemReset()) < 0 ) return status; // check if chip is accessible (it should after ca. 1 mS) if( (status=MIOS32_ENC28J60_ReadETHReg(ESTAT)) < 0 ) return status; if( (status & 0x08) || !(status & ESTAT_CLKRDY) ) return -16; // no access to chip // read and check revision ID, this gives us another check if device is available MIOS32_ENC28J60_BankSel(EREVID); if( (status=MIOS32_ENC28J60_ReadMACReg((u8)EREVID)) < 0 ) return status; rev_id = status; if( !rev_id || rev_id >= 32 ) { return -17; // unsupported revision ID } // Start up in Bank 0 and configure the receive buffer boundary pointers // and the buffer write protect pointer (receive buffer read pointer) WasDiscarded = 1; NextPacketLocation = RXSTART; MIOS32_ENC28J60_BankSel(ERXSTL); status |= MIOS32_ENC28J60_WriteReg(ERXSTL, (RXSTART) & 0xff); status |= MIOS32_ENC28J60_WriteReg(ERXSTH, ((RXSTART) >> 8) & 0xff); status |= MIOS32_ENC28J60_WriteReg(ERXRDPTL, (RXSTOP) & 0xff); status |= MIOS32_ENC28J60_WriteReg(ERXRDPTH, ((RXSTOP) >> 8) & 0xff); status |= MIOS32_ENC28J60_WriteReg(ERXNDL, (RXSTOP) & 0xff); status |= MIOS32_ENC28J60_WriteReg(ERXNDH, ((RXSTOP) >> 8) & 0xff); status |= MIOS32_ENC28J60_WriteReg(ETXSTL, (TXSTART) & 0xff); status |= MIOS32_ENC28J60_WriteReg(ETXSTH, ((TXSTART) >> 8) & 0xff); // Write a permanant per packet control byte of 0x00 status |= MIOS32_ENC28J60_WriteReg(EWRPTL, (TXSTART) & 0xff); status |= MIOS32_ENC28J60_WriteReg(EWRPTH, ((TXSTART) >> 8) & 0xff); status |= MIOS32_ENC28J60_MACPut(0x00); // Enter Bank 1 and configure Receive Filters // (No need to reconfigure - Unicast OR Broadcast with CRC checking is // acceptable) // Write ERXFCON_CRCEN only to ERXFCON to enter promiscuous mode // Promiscious mode example: // status |= MIOS32_ENC28J60_BankSel(ERXFCON); // status |= MIOS32_ENC28J60_WriteReg((u8)ERXFCON, ERXFCON_CRCEN); // Enter Bank 2 and configure the MAC status |= MIOS32_ENC28J60_BankSel(MACON1); // Enable the receive portion of the MAC status |= MIOS32_ENC28J60_WriteReg((u8)MACON1, MACON1_TXPAUS | MACON1_RXPAUS | MACON1_MARXEN); // Pad packets to 60 bytes, add CRC, and check Type/Length field. #if MIOS32_ENC28J60_FULL_DUPLEX status |= MIOS32_ENC28J60_WriteReg((u8)MACON3, MACON3_PADCFG0 | MACON3_TXCRCEN | MACON3_FRMLNEN | MACON3_FULDPX); status |= MIOS32_ENC28J60_WriteReg((u8)MABBIPG, 0x15); #else status |= MIOS32_ENC28J60_WriteReg((u8)MACON3, MACON3_PADCFG0 | MACON3_TXCRCEN | MACON3_FRMLNEN); status |= MIOS32_ENC28J60_WriteReg((u8)MABBIPG, 0x12); #endif // Allow infinite deferals if the medium is continuously busy // (do not time out a transmission if the half duplex medium is // completely saturated with other people's data) status |= MIOS32_ENC28J60_WriteReg((u8)MACON4, MACON4_DEFER); // Late collisions occur beyond 63+8 bytes (8 bytes for preamble/start of frame delimiter) // 55 is all that is needed for IEEE 802.3, but ENC28J60 B5 errata for improper link pulse // collisions will occur less often with a larger number. status |= MIOS32_ENC28J60_WriteReg((u8)MACLCON2, 63); // Set non-back-to-back inter-packet gap to 9.6us. The back-to-back // inter-packet gap (MABBIPG) is set by MACSetDuplex() which is called // later. status |= MIOS32_ENC28J60_WriteReg((u8)MAIPGL, 0x12); status |= MIOS32_ENC28J60_WriteReg((u8)MAIPGH, 0x0C); // Set the maximum packet size which the controller will accept status |= MIOS32_ENC28J60_WriteReg((u8)MAMXFLL, (MIOS32_ENC28J60_MAX_FRAME_SIZE) & 0xff); status |= MIOS32_ENC28J60_WriteReg((u8)MAMXFLH, ((MIOS32_ENC28J60_MAX_FRAME_SIZE) >> 8) & 0xff); // initialize physical MAC address registers status |= MIOS32_ENC28J60_MAC_AddrSet(mac_addr); // Enter Bank 3 and Disable the CLKOUT output to reduce EMI generation status |= MIOS32_ENC28J60_BankSel(ECOCON); status |= MIOS32_ENC28J60_WriteReg((u8)ECOCON, 0x00); // Output off (0V) //status |= MIOS32_ENC28J60_WriteReg((u8)ECOCON, 0x01); // 25.000MHz //status |= MIOS32_ENC28J60_WriteReg((u8)ECOCON, 0x03); // 8.3333MHz (*4 with PLL is 33.3333MHz) // Disable half duplex loopback in PHY. Bank bits changed to Bank 2 as a // side effect. status |= MIOS32_ENC28J60_WritePHYReg(PHCON2, PHCON2_HDLDIS); // Configure LEDA to display LINK status, LEDB to display TX/RX activity status |= MIOS32_ENC28J60_WritePHYReg(PHLCON, 0x3472); // Set the MAC and PHY into the proper duplex state #if MIOS32_ENC28J60_FULL_DUPLEX status |= MIOS32_ENC28J60_WritePHYReg(PHCON1, PHCON1_PDPXMD); #else status |= MIOS32_ENC28J60_WritePHYReg(PHCON1, 0x0000); #endif status |= MIOS32_ENC28J60_BankSel(ERDPTL); // Return to default Bank 0 // Enable packet reception status |= MIOS32_ENC28J60_BFSReg(ECON1, ECON1_RXEN); return (status < 0) ? status : 0; }
///////////////////////////////////////////////////////////////////////////// //! Initializes SPI pins //! \param[in] mode currently only mode 0 supported //! \return < 0 if initialisation failed ///////////////////////////////////////////////////////////////////////////// s32 MIOS32_SPI_Init(u32 mode) { // currently only mode 0 supported if( mode != 0 ) return -1; // unsupported mode DMA_InitTypeDef DMA_InitStructure; DMA_StructInit(&DMA_InitStructure); /////////////////////////////////////////////////////////////////////////// // SPI0 /////////////////////////////////////////////////////////////////////////// #ifndef MIOS32_DONT_USE_SPI0 // disable callback function spi_callback[0] = NULL; // set RC pin(s) to 1 MIOS32_SPI_RC_PinSet(0, 0, 1); // spi, rc_pin, pin_value MIOS32_SPI_RC_PinSet(0, 1, 1); // spi, rc_pin, pin_value // IO configuration MIOS32_SPI_IO_Init(0, MIOS32_SPI_PIN_DRIVER_WEAK_OD); // enable SPI peripheral clock (APB2 == high speed) RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); // enable DMA1 clock RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // DMA Configuration for SPI Rx Event DMA_Cmd(MIOS32_SPI0_DMA_RX_PTR, DISABLE); DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&MIOS32_SPI0_PTR->DR; DMA_InitStructure.DMA_MemoryBaseAddr = 0; // will be configured later DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = 0; // will be configured later DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(MIOS32_SPI0_DMA_RX_PTR, &DMA_InitStructure); // DMA Configuration for SPI Tx Event // (partly re-using previous DMA setup) DMA_Cmd(MIOS32_SPI0_DMA_TX_PTR, DISABLE); DMA_InitStructure.DMA_MemoryBaseAddr = 0; // will be configured later DMA_InitStructure.DMA_BufferSize = 0; // will be configured later DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_Init(MIOS32_SPI0_DMA_TX_PTR, &DMA_InitStructure); // enable SPI SPI_Cmd(MIOS32_SPI0_PTR, ENABLE); // enable SPI interrupts to DMA SPI_I2S_DMACmd(MIOS32_SPI0_PTR, SPI_I2S_DMAReq_Tx | SPI_I2S_DMAReq_Rx, ENABLE); // Configure DMA interrupt MIOS32_IRQ_Install(MIOS32_SPI0_DMA_IRQ_CHANNEL, MIOS32_IRQ_SPI_DMA_PRIORITY); // initial SPI peripheral configuration MIOS32_SPI_TransferModeInit(0, MIOS32_SPI_MODE_CLK1_PHASE1, MIOS32_SPI_PRESCALER_128); #endif /* MIOS32_DONT_USE_SPI0 */ /////////////////////////////////////////////////////////////////////////// // SPI1 /////////////////////////////////////////////////////////////////////////// #ifndef MIOS32_DONT_USE_SPI1 // disable callback function spi_callback[1] = NULL; // set RC pin(s) to 1 MIOS32_SPI_RC_PinSet(1, 0, 1); // spi, rc_pin, pin_value MIOS32_SPI_RC_PinSet(1, 1, 1); // spi, rc_pin, pin_value // IO configuration MIOS32_SPI_IO_Init(1, MIOS32_SPI_PIN_DRIVER_WEAK_OD); // enable SPI peripheral clock (APB1 == slow speed) RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE); // enable DMA1 clock RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // DMA Configuration for SPI Rx Event DMA_Cmd(MIOS32_SPI1_DMA_RX_PTR, DISABLE); DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&MIOS32_SPI1_PTR->DR; DMA_InitStructure.DMA_MemoryBaseAddr = 0; // will be configured later DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = 0; // will be configured later DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(MIOS32_SPI1_DMA_RX_PTR, &DMA_InitStructure); // DMA Configuration for SPI Tx Event // (partly re-using previous DMA setup) DMA_Cmd(MIOS32_SPI1_DMA_TX_PTR, DISABLE); DMA_InitStructure.DMA_MemoryBaseAddr = 0; // will be configured later DMA_InitStructure.DMA_BufferSize = 0; // will be configured later DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_Init(MIOS32_SPI1_DMA_TX_PTR, &DMA_InitStructure); // enable SPI SPI_Cmd(MIOS32_SPI1_PTR, ENABLE); // enable SPI interrupts to DMA SPI_I2S_DMACmd(MIOS32_SPI1_PTR, SPI_I2S_DMAReq_Tx | SPI_I2S_DMAReq_Rx, ENABLE); // Configure DMA interrupt MIOS32_IRQ_Install(MIOS32_SPI1_DMA_IRQ_CHANNEL, MIOS32_IRQ_SPI_DMA_PRIORITY); // initial SPI peripheral configuration MIOS32_SPI_TransferModeInit(1, MIOS32_SPI_MODE_CLK1_PHASE1, MIOS32_SPI_PRESCALER_128); #endif /* MIOS32_DONT_USE_SPI1 */ /////////////////////////////////////////////////////////////////////////// // SPI2 (software emulated) /////////////////////////////////////////////////////////////////////////// #ifndef MIOS32_DONT_USE_SPI2 // disable callback function spi_callback[2] = NULL; // set RC pin(s) to 1 MIOS32_SPI_RC_PinSet(2, 0, 1); // spi, rc_pin, pin_value MIOS32_SPI_RC_PinSet(2, 1, 1); // spi, rc_pin, pin_value // IO configuration MIOS32_SPI_IO_Init(2, MIOS32_SPI_PIN_DRIVER_WEAK_OD); // initial SPI peripheral configuration MIOS32_SPI_TransferModeInit(2, MIOS32_SPI_MODE_CLK1_PHASE1, MIOS32_SPI_PRESCALER_128); #endif /* MIOS32_DONT_USE_SPI2 */ return 0; // no error }