mirror of
https://github.com/cesanta/mongoose.git
synced 2026-10-08 08:54:54 +07:00
115 lines
3.9 KiB
C
115 lines
3.9 KiB
C
// https://arm-software.github.io/CMSIS_5/Driver/html/index.html
|
|
|
|
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_CMSIS) && MG_ENABLE_DRIVER_CMSIS
|
|
|
|
#include "cmsis.h"
|
|
#include "net_builtin.h"
|
|
#include "queue.h"
|
|
|
|
extern ARM_DRIVER_ETH_MAC Driver_ETH_MAC0;
|
|
extern ARM_DRIVER_ETH_PHY Driver_ETH_PHY0;
|
|
|
|
static struct mg_tcpip_if *s_ifp;
|
|
|
|
static void mac_cb(uint32_t);
|
|
static bool cmsis_init(struct mg_tcpip_if *);
|
|
static bool cmsis_up(struct mg_tcpip_if *);
|
|
static size_t cmsis_tx(const void *, size_t, struct mg_tcpip_if *);
|
|
static size_t cmsis_rx(void *, size_t, struct mg_tcpip_if *);
|
|
|
|
struct mg_tcpip_driver mg_tcpip_driver_cmsis = {cmsis_init, cmsis_tx, NULL,
|
|
cmsis_up};
|
|
|
|
static bool cmsis_init(struct mg_tcpip_if *ifp) {
|
|
ARM_ETH_MAC_ADDR addr;
|
|
s_ifp = ifp;
|
|
|
|
ARM_DRIVER_ETH_MAC *mac = &Driver_ETH_MAC0;
|
|
ARM_DRIVER_ETH_PHY *phy = &Driver_ETH_PHY0;
|
|
ARM_ETH_MAC_CAPABILITIES cap = mac->GetCapabilities();
|
|
if (mac->Initialize(mac_cb) != ARM_DRIVER_OK) return false;
|
|
if (phy->Initialize(mac->PHY_Read, mac->PHY_Write) != ARM_DRIVER_OK)
|
|
return false;
|
|
if (cap.event_rx_frame == 0) // polled mode driver
|
|
mg_tcpip_driver_cmsis.rx = cmsis_rx;
|
|
mac->PowerControl(ARM_POWER_FULL);
|
|
if (cap.mac_address) { // driver provides MAC address
|
|
mac->GetMacAddress(&addr);
|
|
memcpy(ifp->mac, &addr, sizeof(ifp->mac));
|
|
} else { // we provide MAC address
|
|
memcpy(&addr, ifp->mac, sizeof(addr));
|
|
mac->SetMacAddress(&addr);
|
|
}
|
|
phy->PowerControl(ARM_POWER_FULL);
|
|
phy->SetInterface(cap.media_interface);
|
|
phy->SetMode(ARM_ETH_PHY_AUTO_NEGOTIATE);
|
|
return true;
|
|
}
|
|
|
|
static size_t cmsis_tx(const void *buf, size_t len, struct mg_tcpip_if *ifp) {
|
|
ARM_DRIVER_ETH_MAC *mac = &Driver_ETH_MAC0;
|
|
if (mac->SendFrame(buf, (uint32_t) len, 0) != ARM_DRIVER_OK) {
|
|
ifp->nerr++;
|
|
return 0;
|
|
}
|
|
ifp->nsent++;
|
|
return len;
|
|
}
|
|
|
|
static bool cmsis_up(struct mg_tcpip_if *ifp) {
|
|
ARM_DRIVER_ETH_PHY *phy = &Driver_ETH_PHY0;
|
|
ARM_DRIVER_ETH_MAC *mac = &Driver_ETH_MAC0;
|
|
bool up = (phy->GetLinkState() == ARM_ETH_LINK_UP) ? 1 : 0; // link state
|
|
if ((ifp->state == MG_TCPIP_STATE_DOWN) && up) { // just went up
|
|
ARM_ETH_LINK_INFO st = phy->GetLinkInfo();
|
|
mac->Control(ARM_ETH_MAC_CONFIGURE,
|
|
(st.speed << ARM_ETH_MAC_SPEED_Pos) |
|
|
(st.duplex << ARM_ETH_MAC_DUPLEX_Pos) |
|
|
ARM_ETH_MAC_ADDRESS_BROADCAST);
|
|
MG_DEBUG(("Link is %uM %s-duplex",
|
|
(st.speed == 2) ? 1000
|
|
: st.speed ? 100
|
|
: 10,
|
|
st.duplex ? "full" : "half"));
|
|
mac->Control(ARM_ETH_MAC_CONTROL_TX, 1);
|
|
mac->Control(ARM_ETH_MAC_CONTROL_RX, 1);
|
|
} else if ((ifp->state != MG_TCPIP_STATE_DOWN) && !up) { // just went down
|
|
mac->Control(ARM_ETH_MAC_FLUSH,
|
|
ARM_ETH_MAC_FLUSH_TX | ARM_ETH_MAC_FLUSH_RX);
|
|
mac->Control(ARM_ETH_MAC_CONTROL_TX, 0);
|
|
mac->Control(ARM_ETH_MAC_CONTROL_RX, 0);
|
|
}
|
|
return up;
|
|
}
|
|
|
|
static void mac_cb(uint32_t ev) {
|
|
if ((ev & ARM_ETH_MAC_EVENT_RX_FRAME) == 0) return;
|
|
ARM_DRIVER_ETH_MAC *mac = &Driver_ETH_MAC0;
|
|
uint32_t len = mac->GetRxFrameSize(); // CRC already stripped
|
|
if (len >= 60 && len <= 1518) { // proper frame
|
|
char *p;
|
|
if (mg_queue_book(&s_ifp->recv_queue, &p, len) >= len) { // have room
|
|
if ((len = mac->ReadFrame((uint8_t *) p, len)) > 0) { // copy succeeds
|
|
mg_queue_add(&s_ifp->recv_queue, len);
|
|
s_ifp->nrecv++;
|
|
}
|
|
return;
|
|
}
|
|
s_ifp->ndrop++;
|
|
}
|
|
mac->ReadFrame(NULL, 0); // otherwise, discard
|
|
}
|
|
|
|
static size_t cmsis_rx(void *buf, size_t buflen, struct mg_tcpip_if *ifp) {
|
|
ARM_DRIVER_ETH_MAC *mac = &Driver_ETH_MAC0;
|
|
uint32_t len = mac->GetRxFrameSize(); // CRC already stripped
|
|
if (len >= 60 && len <= 1518 &&
|
|
((len = mac->ReadFrame(buf, (uint32_t) buflen)) > 0))
|
|
return len;
|
|
if (len > 0) mac->ReadFrame(NULL, 0); // discard bad frames
|
|
(void) ifp;
|
|
return 0;
|
|
}
|
|
|
|
#endif
|