///////////////////////////////////////////////////////////////////////////// //! Checks if the chip is still connected by reading the revision ID.<BR> //! This takes ca. 2 uS //! //! If the ID value is within the range of 0x01..0x1f, MIOS32_ENC28J60_PowerOn() //! will be called by this function to initialize the device completely. //! //! Example for Connection/Disconnection detection: //! \code //! // this function is called each second from a low-priority task //! // If multiple tasks are accessing the ENC28J60 chip, add a semaphore/mutex //! // to avoid IO access collisions with other tasks! //! u8 enc28j60_available; //! s32 ETHERNET_CheckENC28J60(void) //! { //! // check if ENC28J60 is connected //! u8 prev_enc28j60_available = enc28j60_available; //! enc28j60_available = MIOS32_ENC28J60_CheckAvailable(prev_enc28j60_available); //! //! if( enc28j60_available && !prev_enc28j60_available ) { //! // ENC28J60 has been connected //! //! // now it's possible to receive/send packages //! //! } else if( !enc28j60_available && prev_enc28j60_available ) { //! // ENC28J60 has been disconnected //! //! // here you can notify your application about this state //! } //! //! return 0; // no error //! } //! \endcode //! \param[in] was_available should only be set if the ENC28J60 was previously available //! \return 0 if no response from ENC28J60 //! \return 1 if ENC28J60 is accessible ///////////////////////////////////////////////////////////////////////////// s32 MIOS32_ENC28J60_CheckAvailable(u8 was_available) { s32 status = 0; MIOS32_ENC28J60_MUTEX_TAKE; if( (status=MIOS32_SPI_TransferModeInit(MIOS32_ENC28J60_SPI, MIOS32_SPI_MODE_CLK0_PHASE0, MIOS32_SPI_PRESCALER_4)) < 0 ) goto error; // read revision ID to check if ENC28J60 is connected MIOS32_ENC28J60_BankSel(EREVID); if( (status=MIOS32_ENC28J60_ReadMACReg((u8)EREVID)) < 0 ) goto error; // chip not connected if value < 1 or >= 32 if( !status || status >= 32 ) goto error; // initialize chip if it has been detected if( !was_available ) { // run power-on sequence if( MIOS32_ENC28J60_PowerOn() < 0 ) goto error; } MIOS32_ENC28J60_MUTEX_GIVE; return 1; // ENC28J60 available error: MIOS32_ENC28J60_MUTEX_GIVE; return 0; // ENC28J60 not available. }
///////////////////////////////////////////////////////////////////////////// // This hook is called after startup to initialize the application ///////////////////////////////////////////////////////////////////////////// void APP_Init(void) { // create semaphores xMIDIINSemaphore = xSemaphoreCreateRecursiveMutex(); xMIDIOUTSemaphore = xSemaphoreCreateRecursiveMutex(); // install SysEx callback MIOS32_MIDI_SysExCallback_Init(APP_SYSEX_Parser); // install MIDI Rx/Tx callback functions MIOS32_MIDI_DirectRxCallback_Init(&NOTIFY_MIDI_Rx); MIOS32_MIDI_DirectTxCallback_Init(&NOTIFY_MIDI_Tx); // install timeout callback function MIOS32_MIDI_TimeOutCallback_Init(&NOTIFY_MIDI_TimeOut); // limit the number of DIN/DOUT SRs which will be scanned for faster scan rate MIOS32_SRIO_ScanNumSet(2); // init keyboard functions KEYBOARD_Init(0); // read EEPROM content PRESETS_Init(0); // init MIDI port/router handling MIDI_PORT_Init(0); MIDI_ROUTER_Init(0); // init terminal TERMINAL_Init(0); // init MIDImon MIDIMON_Init(0); // start uIP task UIP_TASK_Init(0); // print welcome message on MIOS terminal MIOS32_MIDI_SendDebugMessage("\n"); MIOS32_MIDI_SendDebugMessage("=================\n"); MIOS32_MIDI_SendDebugMessage("%s\n", MIOS32_LCD_BOOT_MSG_LINE1); MIOS32_MIDI_SendDebugMessage("=================\n"); MIOS32_MIDI_SendDebugMessage("\n"); // speed up SPI transfer rate (was MIOS32_SPI_PRESCALER_128, initialized by MIOS32_SRIO_Init()) MIOS32_SPI_TransferModeInit(MIOS32_SRIO_SPI, MIOS32_SPI_MODE_CLK1_PHASE1, MIOS32_SPI_PRESCALER_128); // prescaler 64 results into a transfer rate of 0.64 uS per bit // when 2 SRs are transfered, we are able to scan the whole 16x8 matrix in 300 uS // standard SRIO scan has been disabled in programming_models/traditional/main.c via MIOS32_DONT_SERVICE_SRIO_SCAN in mios32_config.h // start the scan here - and retrigger it whenever it's finished APP_SRIO_ServicePrepare(); MIOS32_SRIO_ScanStart(APP_SRIO_ServiceFinish); // start tasks xTaskCreate(TASK_Period_1mS, (signed portCHAR *)"1mS", configMINIMAL_STACK_SIZE, NULL, PRIORITY_TASK_PERIOD_1mS, NULL); }
///////////////////////////////////////////////////////////////////////////// // 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); }
///////////////////////////////////////////////////////////////////////////// //! Receives a package from ENC28J60 chip //! param[in] buffer Pointer to buffer which gets the playload //! param[in] buffer_size Max. number of bytes which can be received //! \return < 0 on errors //! \return -16 if inconsistencies have been detected, and the ENC28J60 device has been reseted //! \return 0 if no package has been received //! \return > 0 number of received bytes ///////////////////////////////////////////////////////////////////////////// s32 MIOS32_ENC28J60_PackageReceive(u8 *buffer, u16 buffer_size) { s32 status = 0; s32 package_count; u16 packet_len = 0; MIOS32_ENC28J60_MUTEX_TAKE; // re-init SPI port for fast frequency access (ca. 18 MBit/s) // this is required for the case that the SPI port is shared with other devices if( (status=MIOS32_SPI_TransferModeInit(MIOS32_ENC28J60_SPI, MIOS32_SPI_MODE_CLK0_PHASE0, MIOS32_SPI_PRESCALER_4)) < 0 ) goto error; // Test if at least one packet has been received and is waiting status |= MIOS32_ENC28J60_BankSel(EPKTCNT); package_count = MIOS32_ENC28J60_ReadETHReg((u8)EPKTCNT); status |= MIOS32_ENC28J60_BankSel(ERDPTL); if( status < 0 ) goto error; if( package_count <= 0 ) { status=package_count; goto error; } // Make absolutely certain that any previous packet was discarded if( !WasDiscarded ) { status = MIOS32_ENC28J60_MACDiscardRx(); status = (status < 0) ? status : 0; goto error; } // Set the SPI read pointer to the beginning of the next unprocessed packet u16 CurrentPacketLocation = NextPacketLocation; status |= MIOS32_ENC28J60_WriteReg(ERDPTL, CurrentPacketLocation & 0xff); status |= MIOS32_ENC28J60_WriteReg(ERDPTH, (CurrentPacketLocation >> 8) & 0xff); if( status < 0 ) goto error; // Obtain the MAC header from the Ethernet buffer ENC_PREAMBLE header; status |= MIOS32_ENC28J60_MACGetArray((u8 *)&header, sizeof(header)); // Validate the data returned from the ENC28J60. Random data corruption, // such as if a single SPI bit error occurs while communicating or a // momentary power glitch could cause this to occur in rare circumstances. if( header.NextPacketPointer > RXSTOP || (header.NextPacketPointer & 1) || header.StatusVector.bits.Zero || header.StatusVector.bits.ByteCount > MIOS32_ENC28J60_MAX_FRAME_SIZE ) { MIOS32_MIDI_SendDebugMessage("[MIOS32_ENC28J60_PackageReceive] glitch detected - Ptr: %04x, Status: %04x (max: %04x) %02x%02x\n", header.NextPacketPointer, header.StatusVector.bits.ByteCount, MIOS32_ENC28J60_MAX_FRAME_SIZE, header.StatusVector.v[3], header.StatusVector.v[2]); // Reset device (must keep mutex) MIOS32_ENC28J60_PowerOn(); // no packet received status=-16; goto error; } // Save the location where the hardware will write the next packet to NextPacketLocation = header.NextPacketPointer; // Mark this packet as discardable WasDiscarded = 0; // empty package or CRC/symbol errors? packet_len = header.StatusVector.bits.ByteCount; if( !packet_len || header.StatusVector.bits.CRCError || !header.StatusVector.bits.ReceiveOk ) { status = MIOS32_ENC28J60_MACDiscardRx(); // discard package immediately status = (status < 0) ? status : 0; goto error; } // ensure that we don't read more bytes than the buffer can store if( packet_len > buffer_size ) packet_len = buffer_size; // read bytes into buffer status = MIOS32_ENC28J60_MACGetArray(buffer, packet_len); // discard package immediately status |= MIOS32_ENC28J60_MACDiscardRx(); // No more processing so can safely give mutex back. error: MIOS32_ENC28J60_MUTEX_GIVE; if( status < 0 ) return status; return packet_len; // no error: return packet length }
///////////////////////////////////////////////////////////////////////////// //! Changes the MAC address. //! //! Usually called by MIOS32_ENC28J60_PowerOn(), but could also be used //! during runtime. //! //! The default MAC address is predefined by MIOS32_ENC28J60_MY_MAC_ADDR[123456] //! and can be overruled in mios32_config.h if desired. //! //! \param[in] new_mac_addr an array with 6 bytes which define the MAC //! address. If all bytes are 0 (default), the serial number of STM32 will be //! taken instead, which should be unique in your private network. //! \return < 0 on errors ///////////////////////////////////////////////////////////////////////////// s32 MIOS32_ENC28J60_MAC_AddrSet(u8 new_mac_addr[6]) { s32 status; // re-init SPI port for fast frequency access (ca. 18 MBit/s) // this is required for the case that the SPI port is shared with other devices if( (status=MIOS32_SPI_TransferModeInit(MIOS32_ENC28J60_SPI, MIOS32_SPI_MODE_CLK0_PHASE0, MIOS32_SPI_PRESCALER_4)) < 0 ) return status; // check for all-zero int i; int ored = 0; for(i=0; i<6; ++i) ored |= new_mac_addr[i]; if( ored ) { // MAC address != 0 -> take over new address memcpy(mac_addr, new_mac_addr, 6); } else { // get serial number char serial[32]; MIOS32_SYS_SerialNumberGet(serial); int len = strlen(serial); if( len < 12 ) { // no serial number or not large enough - we should at least set the MAC address to != 0 for(i=0; i<6; ++i) mac_addr[i] = i; } else { #if 0 for(i=0; i<6; ++i) { // convert hex string to dec char digitl = serial[len-i*2 - 1]; char digith = serial[len-i*2 - 2]; mac_addr[i] = ((digitl >= 'A') ? (digitl-'A'+10) : (digitl-'0')) | (((digith >= 'A') ? (digith-'A'+10) : (digith-'0')) << 4); #else // TK: for some reasons, my Fritzbox router doesn't accept MACs that are not starting with 0x00 mac_addr[0] = 0x00; for(i=1; i<6; ++i) { // convert hex string to dec char digitl = serial[len-(i-1)*2 - 1]; char digith = serial[len-(i-1)*2 - 2]; mac_addr[i] = ((digitl >= 'A') ? (digitl-'A'+10) : (digitl-'0')) | (((digith >= 'A') ? (digith-'A'+10) : (digith-'0')) << 4); #endif } } } status |= MIOS32_ENC28J60_BankSel(MAADR1); status |= MIOS32_ENC28J60_WriteReg((u8)MAADR1, mac_addr[0]); status |= MIOS32_ENC28J60_WriteReg((u8)MAADR2, mac_addr[1]); status |= MIOS32_ENC28J60_WriteReg((u8)MAADR3, mac_addr[2]); status |= MIOS32_ENC28J60_WriteReg((u8)MAADR4, mac_addr[3]); status |= MIOS32_ENC28J60_WriteReg((u8)MAADR5, mac_addr[4]); status |= MIOS32_ENC28J60_WriteReg((u8)MAADR6, mac_addr[5]); return status; } ///////////////////////////////////////////////////////////////////////////// //! Returns the current MAC address //! \return u8 pointer with 6 bytes ///////////////////////////////////////////////////////////////////////////// u8 *MIOS32_ENC28J60_MAC_AddrGet(void) { return mac_addr; } ///////////////////////////////////////////////////////////////////////////// //! Sends a package to the ENC28J60 chip //! param[in] buffer Pointer to buffer which contains the playload //! param[in] len number of bytes which should be sent //! param[in] buffer2 Pointer to optional second buffer which contains additional playload //! (can be NULL if no additional data) //! param[in] len2 number of bytes in second buffer //! (should be 0 if no additional data) //! \return < 0 on errors //! \return -16 if previous package hasn't been sent yet (this is checked //! 1000 times before the function exits) ///////////////////////////////////////////////////////////////////////////// s32 MIOS32_ENC28J60_PackageSend(u8 *buffer, u16 len, u8 *buffer2, u16 len2) { s32 status = 0; MIOS32_ENC28J60_MUTEX_TAKE; // re-init SPI port for fast frequency access (ca. 18 MBit/s) // this is required for the case that the SPI port is shared with other devices if( (status=MIOS32_SPI_TransferModeInit(MIOS32_ENC28J60_SPI, MIOS32_SPI_MODE_CLK0_PHASE0, MIOS32_SPI_PRESCALER_4)) < 0 ) goto error; // wait until a new package can be transmitted int timeout_ctr = 1000; while( --timeout_ctr > 0 ) { status = MIOS32_ENC28J60_ReadETHReg(ECON1); if( status < 0 ) goto error; if( !(status & ECON1_TXRTS) ) break; } if( timeout_ctr == 0 ) { status=-16; goto error; } // Set the SPI write pointer to the beginning of the transmit buffer status |= MIOS32_ENC28J60_BankSel(EWRPTL); status |= MIOS32_ENC28J60_WriteReg(EWRPTL, TXSTART & 0xff); status |= MIOS32_ENC28J60_WriteReg(EWRPTH, (TXSTART >> 8) & 0xff); if( status < 0 ) goto error; // Calculate where to put the TXND pointer u16 end_addr = TXSTART + len + len2; // package control byte has already been considered in this calculation (+1 .. -1) // Write the TXND pointer into the registers, given the dataLen given status |= MIOS32_ENC28J60_WriteReg(ETXNDL, end_addr & 0xff); status |= MIOS32_ENC28J60_WriteReg(ETXNDH, (end_addr >> 8) & 0xff); if( status < 0 ) goto error; // per-packet control byte: status |= MIOS32_ENC28J60_MACPut(0x07); // enable CRC calculation and padding to 60 bytes // send buffer status |= MIOS32_ENC28J60_MACPutArray(buffer, len); // send second buffer if available if( buffer2 != NULL && len2 ) { status |= MIOS32_ENC28J60_MACPutArray(buffer2, len2); } // Reset transmit logic if a TX Error has previously occured // This is a silicon errata workaround status |= MIOS32_ENC28J60_BFSReg(ECON1, ECON1_TXRST); status |= MIOS32_ENC28J60_BFCReg(ECON1, ECON1_TXRST); status |= MIOS32_ENC28J60_BFCReg(EIR, EIR_TXERIF | EIR_TXIF); // Start the transmission status |= MIOS32_ENC28J60_BFSReg(ECON1, ECON1_TXRTS); // This one is a bit pointless but we may add special rev code below! if( status < 0 ) goto error; // Revision B5 and B7 silicon errata workaround if( rev_id == 0x05 || rev_id == 0x06 ) { // TODO --- add a lot of code here } error: // We have finished with the mutex. MIOS32_ENC28J60_MUTEX_GIVE; return status; }
///////////////////////////////////////////////////////////////////////////// //! 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 }