From 1dc7d758f96dd2b9bd7b03f01ca032d68b696cf0 Mon Sep 17 00:00:00 2001 From: root Date: Sun, 2 Nov 2014 10:14:39 +0000 Subject: fish --- libopencm3/lib/ethernet/mac.c | 43 ++++ libopencm3/lib/ethernet/mac_stm32fxx7.c | 378 +++++++++++++++++++++++++++++++ libopencm3/lib/ethernet/phy.c | 64 ++++++ libopencm3/lib/ethernet/phy_ksz8051mll.c | 89 ++++++++ 4 files changed, 574 insertions(+) create mode 100644 libopencm3/lib/ethernet/mac.c create mode 100644 libopencm3/lib/ethernet/mac_stm32fxx7.c create mode 100644 libopencm3/lib/ethernet/phy.c create mode 100644 libopencm3/lib/ethernet/phy_ksz8051mll.c (limited to 'libopencm3/lib/ethernet') diff --git a/libopencm3/lib/ethernet/mac.c b/libopencm3/lib/ethernet/mac.c new file mode 100644 index 0000000..3b7db12 --- /dev/null +++ b/libopencm3/lib/ethernet/mac.c @@ -0,0 +1,43 @@ +/** @defgroup ethernet_mac_file MAC Generic Drivers + * + * @ingroup ETH + * + * @brief Ethernet MAC Generic Drivers + * + * @version 1.0.0 + * @author @htmlonly © @endhtmlonly 2013 Frantisek Burian + * + * @date 1 September 2013 + * + * + * LGPL License Terms @ref lgpl_license + */ + +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2013 Frantisek Burian + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#include +#include + +/**@{*/ + + +/*---------------------------------------------------------------------------*/ + +/**@}*/ diff --git a/libopencm3/lib/ethernet/mac_stm32fxx7.c b/libopencm3/lib/ethernet/mac_stm32fxx7.c new file mode 100644 index 0000000..16f76a8 --- /dev/null +++ b/libopencm3/lib/ethernet/mac_stm32fxx7.c @@ -0,0 +1,378 @@ +/** @defgroup ethernet_mac_stm32fxx7_file MAC STM32Fxx7 + * + * @ingroup ETH + * + * @brief Ethernet MAC STM32Fxx7 Drivers + * + * @version 1.0.0 + * @author @htmlonly © @endhtmlonly 2013 Frantisek Burian + * + * @date 1 September 2013 + * + * + * LGPL License Terms @ref lgpl_license + */ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2013 Frantisek Burian + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#include +#include +#include +#include +#include + +/**@{*/ + +uint32_t TxBD; +uint32_t RxBD; + +/*---------------------------------------------------------------------------*/ +/** @brief Set MAC to the PHY + * + * @param[in] mac uint8_t* Desired MAC + */ +void eth_set_mac(uint8_t *mac) +{ + ETH_MACAHR(0) = ((uint32_t)mac[5] << 8) | (uint32_t)mac[4] | + ETH_MACA0HR_MACA0H; + ETH_MACALR(0) = ((uint32_t)mac[3] << 24) | ((uint32_t)mac[2] << 16) | + ((uint32_t)mac[1] << 8) | mac[0]; +} + +/*---------------------------------------------------------------------------*/ +/** @brief Initialize descriptors + * + * @param[in] buf uint8_t* Buffer for the descriptors + * @param[in] nTx uint32_t Count of Transmit Descriptors + * @param[in] nRx uint32_t Count of Receive Descriptors + * @param[in] cTx uint32_t Bytes in each Transmit Descriptor + * @param[in] cRx uint32_t Bytes in each Receive Descriptor + * @param[in] isext bool true, if extended descriptors should be used + */ +void eth_desc_init(uint8_t *buf, uint32_t nTx, uint32_t nRx, uint32_t cTx, + uint32_t cRx, bool isext) +{ + memset(buf, 0, nTx * cTx + nRx * cRx); + + uint32_t bd = (uint32_t)buf; + uint32_t sz = isext ? ETH_DES_EXT_SIZE : ETH_DES_STD_SIZE; + + /* enable / disable extended frames */ + if (isext) { + ETH_DMABMR |= ETH_DMABMR_EDFE; + } else { + ETH_DMABMR &= ~ETH_DMABMR_EDFE; + } + + TxBD = bd; + while (--nTx > 0) { + ETH_DES0(bd) = ETH_TDES0_TCH; + ETH_DES2(bd) = bd + sz; + ETH_DES3(bd) = bd + sz + cTx; + bd = ETH_DES3(bd); + } + + ETH_DES0(bd) = ETH_TDES0_TCH; + ETH_DES2(bd) = bd + sz; + ETH_DES3(bd) = TxBD; + bd += sz + cTx; + + RxBD = bd; + while (--nRx > 0) { + ETH_DES0(bd) = ETH_RDES0_OWN; + ETH_DES1(bd) = ETH_RDES1_RCH | cRx; + ETH_DES2(bd) = bd + sz; + ETH_DES3(bd) = bd + sz + cRx; + bd = ETH_DES3(bd); + } + + ETH_DES0(bd) = ETH_RDES0_OWN; + ETH_DES1(bd) = ETH_RDES1_RCH | cRx; + ETH_DES2(bd) = bd + sz; + ETH_DES3(bd) = RxBD; + + ETH_DMARDLAR = (uint32_t) RxBD; + ETH_DMATDLAR = (uint32_t) TxBD; +} + +/*---------------------------------------------------------------------------*/ +/** @brief Transmit packet + * + * @param[in] ppkt uint8_t* Pointer to the beginning of the packet + * @param[in] n uint32_t Size of the packet + * @returns bool true, if success + */ +bool eth_tx(uint8_t *ppkt, uint32_t n) +{ + if (ETH_DES0(TxBD) & ETH_TDES0_OWN) { + return false; + } + + memcpy((void *)ETH_DES2(TxBD), ppkt, n); + + ETH_DES1(TxBD) = n & ETH_TDES1_TBS1; + ETH_DES0(TxBD) |= ETH_TDES0_LS | ETH_TDES0_FS | ETH_TDES0_OWN; + TxBD = ETH_DES3(TxBD); + + if (ETH_DMASR & ETH_DMASR_TBUS) { + ETH_DMASR = ETH_DMASR_TBUS; + ETH_DMATPDR = 0; + } + + return true; +} + +/*---------------------------------------------------------------------------*/ +/** @brief Receive packet + * + * @param[inout] ppkt uint8_t* Pointer to the data buffer where to store data + * @param[inout] len uint32_t* Pointer to the variable with the packet length + * @param[in] maxlen uint32_t Maximum length of the packet + * @returns bool true, if the buffer contains readed packet data + */ +bool eth_rx(uint8_t *ppkt, uint32_t *len, uint32_t maxlen) +{ + bool fs = false; + bool ls = false; + bool overrun = false; + uint32_t l = 0; + + while (!(ETH_DES0(RxBD) & ETH_RDES0_OWN) && !ls) { + l = (ETH_DES0(RxBD) & ETH_RDES0_FL) >> ETH_RDES0_FL_SHIFT; + + fs |= ETH_DES0(RxBD) & ETH_RDES0_FS; + ls |= ETH_DES0(RxBD) & ETH_RDES0_LS; + /* frame buffer overrun ?*/ + overrun |= fs && (maxlen < l); + + if (fs && !overrun) { + memcpy(ppkt, (void *)ETH_DES2(RxBD), l); + ppkt += l; + *len += l; + maxlen -= l; + } + + ETH_DES0(RxBD) = ETH_RDES0_OWN; + RxBD = ETH_DES3(RxBD); + } + + if (ETH_DMASR & ETH_DMASR_RBUS) { + ETH_DMASR = ETH_DMASR_RBUS; + ETH_DMARPDR = 0; + } + + return fs && ls && !overrun; +} + +/*---------------------------------------------------------------------------*/ +/** @brief Start the Ethernet DMA processing + */ +void eth_start(void) +{ + ETH_MACCR |= ETH_MACCR_TE; + ETH_DMAOMR |= ETH_DMAOMR_FTF; + ETH_MACCR |= ETH_MACCR_RE; + + ETH_DMAOMR |= ETH_DMAOMR_ST; + ETH_DMAOMR |= ETH_DMAOMR_SR; +} + +/*---------------------------------------------------------------------------*/ +/** @brief Initialize ethernet + * + * This function will initialize ethernet, set up clocks, and initialize DMA. + * + * @param[in] clock enum eth_clk Core clock speed + */ +void eth_init(enum eth_clk clock) +{ + ETH_MACMIIAR = clock; + phy_reset(); + + ETH_MACCR = ETH_MACCR_CSTF | ETH_MACCR_FES | ETH_MACCR_DM | + ETH_MACCR_APCS | ETH_MACCR_RD; + ETH_MACFFR = ETH_MACFFR_RA | ETH_MACFFR_PM; + ETH_MACHTHR = 0; /* pass all frames */ + ETH_MACHTLR = 0; + ETH_MACFCR = (0x100 << ETH_MACFCR_PT_SHIFT); + ETH_MACVLANTR = 0; + ETH_DMAOMR = ETH_DMAOMR_DTCEFD | ETH_DMAOMR_RSF | ETH_DMAOMR_DFRF | + ETH_DMAOMR_TSF | ETH_DMAOMR_FEF | ETH_DMAOMR_OSF; + ETH_DMABMR = ETH_DMABMR_AAB | ETH_DMABMR_FB | + (32 << ETH_DMABMR_RDP_SHIFT) | (32 << ETH_DMABMR_PBL_SHIFT) | + ETH_DMABMR_PM_2_1 | ETH_DMABMR_USP; +} + +/*---------------------------------------------------------------------------*/ +/** @brief Enable the Ethernet IRQ + * + * @param[in] reason uint32_t Which irq will be enabled + */ +void eth_irq_enable(uint32_t reason) +{ + ETH_DMAIER |= reason; +} + +/*---------------------------------------------------------------------------*/ +/** @brief Disable the Ethernet IRQ + * + * @param[in] reason uint32_t Which irq will be disabled + */ +void eth_irq_disable(uint32_t reason) +{ + ETH_DMAIER &= ~reason; +} + +/*---------------------------------------------------------------------------*/ +/** @brief Check if IRQ is pending + * + * @param[in] reason uint32_t Which irq type has to be tested + * @returns bool true, if IRQ is pending + */ +bool eth_irq_is_pending(uint32_t reason) +{ + return (ETH_DMASR & reason) != 0; +} + +/*---------------------------------------------------------------------------*/ +/** @brief Check if IRQ is pending, and acknowledge it + * + * @param[in] reason uint32_t Which irq type has to be tested + * @returns bool true, if IRQ is pending + */ +bool eth_irq_ack_pending(uint32_t reason) +{ + reason &= ETH_DMASR; + ETH_DMASR = reason; + return reason != 0; +} + +/*---------------------------------------------------------------------------*/ +/** @brief Enable checksum offload feature + * + * This function will enable the Checksum offload feature for all of the + * transmit descriptors. Note to use this feature, descriptors must be in + * extended format. + */ +void eth_enable_checksum_offload(void) +{ + uint32_t tab = TxBD; + do { + ETH_DES0(tab) |= ETH_TDES0_CIC_IPPLPH; + tab = ETH_DES3(tab); + } + while (tab != TxBD); + + ETH_MACCR |= ETH_MACCR_IPCO; +} + +/*---------------------------------------------------------------------------*/ +/** @brief Process pending SMI transaction and wait to be done. + */ +static void eth_smi_transact(void) +{ + /* Begin transaction. */ + ETH_MACMIIAR |= ETH_MACMIIAR_MB; + + /* Wait for not busy. */ + while (ETH_MACMIIAR & ETH_MACMIIAR_MB); +} + +/*---------------------------------------------------------------------------*/ +/** @brief Write 16-bit register to the PHY + * + * @param[in] phy uint8_t ID of the PHY (defaults to 1) + * @param[in] reg uint8_t Register address + * @param[in] data uint16_t Data to write + */ +void eth_smi_write(uint8_t phy, uint8_t reg, uint16_t data) +{ + /* Write operation MW=1*/ + ETH_MACMIIAR = (ETH_MACMIIAR & ETH_MACMIIAR_CR) | /* save clocks */ + (phy << ETH_MACMIIAR_PA_SHIFT) | + (reg << ETH_MACMIIAR_MR_SHIFT) | + ETH_MACMIIAR_MW; + + ETH_MACMIIDR = data & ETH_MACMIIDR_MD; + + eth_smi_transact(); +} + +/*---------------------------------------------------------------------------*/ +/** @brief Read the 16-bit register from the PHY + * + * @param[in] phy uint8_t ID of the PHY (defaults to 1) + * @param[in] reg uint8_t Register address + * @returns uint16_t Readed data + */ +uint16_t eth_smi_read(uint8_t phy, uint8_t reg) +{ + /* Read operation MW=0*/ + ETH_MACMIIAR = (ETH_MACMIIAR & ETH_MACMIIAR_CR) | /* save clocks */ + (phy << ETH_MACMIIAR_PA_SHIFT) | + (reg << ETH_MACMIIAR_MR_SHIFT); + + eth_smi_transact(); + + return (uint16_t)(ETH_MACMIIDR & ETH_MACMIIDR_MD); +} + +/*---------------------------------------------------------------------------*/ +/** @brief Process the bit-operation on PHY register + * + * @param[in] phy uint8_t ID of the PHY (defaults to 1) + * @param[in] reg uint8_t Register address + * @param[in] bits uint16_t Bits that have to be set (or'ed) + * @param[in] mask uint16_t Bits that have to be clear (and'ed) + */ +void eth_smi_bit_op(uint8_t phy, uint8_t reg, uint16_t bits, uint16_t mask) +{ + uint16_t val = eth_smi_read(phy, reg); + eth_smi_write(phy, reg, (val & mask) | bits); +} + +/*---------------------------------------------------------------------------*/ +/** @brief Clear bits in the register + * + * @param[in] phy uint8_t ID of the PHY (defaults to 1) + * @param[in] reg uint8_t Register address + * @param[in] clearbits uint16_t Bits that have to be cleared + */ +void eth_smi_bit_clear(uint8_t phy, uint8_t reg, uint16_t clearbits) +{ + uint16_t val = eth_smi_read(phy, reg); + eth_smi_write(phy, reg, val & (uint16_t)~(clearbits)); +} + +/*---------------------------------------------------------------------------*/ +/** @brief Set bits in the register + * + * @param[in] phy uint8_t ID of the PHY (defaults to 1) + * @param[in] reg uint8_t Register address + * @param[in] bits uint16_t Bits that have to be set (or'ed) + */ +void eth_smi_bit_set(uint8_t phy, uint8_t reg, uint16_t setbits) +{ + uint16_t val = eth_smi_read(phy, reg); + eth_smi_write(phy, reg, val | setbits); +} + +/*---------------------------------------------------------------------------*/ + +/**@}*/ diff --git a/libopencm3/lib/ethernet/phy.c b/libopencm3/lib/ethernet/phy.c new file mode 100644 index 0000000..4866198 --- /dev/null +++ b/libopencm3/lib/ethernet/phy.c @@ -0,0 +1,64 @@ +/** @defgroup ethernet_phy_file PHY Generic Drivers + * + * @ingroup ETH + * + * @brief Ethernet PHY Generic Drivers + * + * @version 1.0.0 + * @author @htmlonly © @endhtmlonly 2013 Frantisek Burian + * + * @date 1 September 2013 + * + * + * LGPL License Terms @ref lgpl_license + */ + +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2013 Frantisek Burian + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#include +#include + +/**@{*/ + +/*---------------------------------------------------------------------------*/ +/** @brief Is the link up ? + * + * @returns bool true, if link is up + */ +bool phy_link_isup(void) +{ + return eth_smi_read(1, PHY_REG_BSR) & PHY_REG_BSR_UP; +} + +/*---------------------------------------------------------------------------*/ +/** @brief Reset the PHY + * + * Reset the PHY chip and wait for done + */ +void phy_reset(void) +{ + eth_smi_write(1, PHY_REG_BCR, PHY_REG_BCR_RESET); + + while (eth_smi_read(1, PHY_REG_BCR) & PHY_REG_BCR_RESET); +} + +/*---------------------------------------------------------------------------*/ + +/**@}*/ diff --git a/libopencm3/lib/ethernet/phy_ksz8051mll.c b/libopencm3/lib/ethernet/phy_ksz8051mll.c new file mode 100644 index 0000000..1faae4f --- /dev/null +++ b/libopencm3/lib/ethernet/phy_ksz8051mll.c @@ -0,0 +1,89 @@ +/** @defgroup ethernet_phy_ksz8051mll_file PHY KSZ8051MLL + * + * @ingroup ETH + * + * @brief Ethernet PHY STM32Fxx7 Drivers + * + * @version 1.0.0 + * @author @htmlonly © @endhtmlonly 2013 Frantisek Burian + * + * @date 1 September 2013 + * + * LGPL License Terms @ref lgpl_license + */ + +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2013 Frantisek Burian + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#include +#include +#include + + +/**@{*/ + +/*---------------------------------------------------------------------------*/ +/** @brief Get the current link status + * + * Retrieve the link speed and duplex status of the link. + * + * @returns ::phy_status Link status + */ +enum phy_status phy_link_status(void) +{ + return eth_smi_read(1, PHY_REG_CR1) & 0x07; +} + +/*---------------------------------------------------------------------------*/ +/** @brief Force autonegotiation + * + * Force the autonegotiation and set link speed and duplex mode of the link + * + * @param[in] mode enum phy_status Desired link status + */ +void phy_autoneg_force(enum phy_status mode) +{ + uint16_t bst = 0; + + if ((mode == LINK_FD_10M) || (mode == LINK_FD_100M) || + (mode == LINK_FD_1000M) || (mode == LINK_FD_10000M)) { + bst |= PHY_REG_BCR_FD; + } + + if ((mode == LINK_FD_100M) || (mode == LINK_FD_100M)) { + bst |= PHY_REG_BCR_100M; + } + + eth_smi_bit_op(1, PHY_REG_BCR, bst, + ~(PHY_REG_BCR_AN | PHY_REG_BCR_100M | PHY_REG_BCR_FD)); +} + +/*---------------------------------------------------------------------------*/ +/** @brief Enable the autonegotiation + * + * Enable the autonegotiation of the link speed and duplex mode + */ +void phy_autoneg_enable(void) +{ + eth_smi_bit_set(1, PHY_REG_BCR, PHY_REG_BCR_AN | PHY_REG_BCR_ANRST); +} + +/*---------------------------------------------------------------------------*/ + +/**@}*/ -- cgit v1.2.3