Цитата(Sagittarius @ May 16 2012, 10:27)

Но при полной оптимизации дохнет драйвер ethernet от ST :-)
Можно, конечно, снижать оптимизацию выборочно. Но по-хорошему такой драйвер надо оторвать и выбросить.
Кстати, когда я ваял свой драйвер ethernet для STM32 (uIP), то подивился, насколько просто это оказалось. Всего 200 строчек:
CODE
/**
* @file stm32eth.h
* @brief Драйвер Ethernet для STM32
*/
#include "stm32eth.h"
#include "stm32f2regs.h"
#include "timer.h"
#include "net/uip.h"
#include <string.h>
#define SMI_TMPL 0x00000004 /* sets SMI clock range and PHY address */
#define RX_BUF_SIZE 256
#define RX_RING_SIZE 32
static bool link, act;
/* the only TX descriptor used in this program */
static uint32_t volatile tx_desc[4] = { 0, 0, (uint32_t)uip_buf, 0 };
static uint32_t volatile rx_desc[RX_RING_SIZE][4];
static uint8_t volatile rx_buf[RX_RING_SIZE][RX_BUF_SIZE];
/* first descriptor in frame, next descriptor to check */
static unsigned int rx_first, rx_cur;
static bool
smi_busy(void)
{
return (ETH_MACMIIAR & 1) != 0;
}
static void
smi_write(int reg, int val)
{
ETH_MACMIIDR = val;
ETH_MACMIIAR = (reg << 6) | SMI_TMPL | 3;
while (smi_busy())
{
/* wait */
}
}
static void
smi_start_read(int reg)
{
ETH_MACMIIAR = (reg << 6) | SMI_TMPL | 1;
}
static int
smi_read_data(void)
{
return ETH_MACMIIDR;
}
static void
phy_init(void)
{
smi_write(0, 0x1100);
smi_write(4, 0x0021);/* auto-negotiate 10Mb half-duplex only */
}
static void
fill_rx_desc(void)
{
int i;
for (i = 0; i < RX_RING_SIZE; i++)
{
rx_desc[i][0] = (1u << 31); /* OWN bit */
rx_desc[i][1] = RX_BUF_SIZE;
rx_desc[i][2] = (uint32_t)&rx_buf[i];
}
rx_desc[RX_RING_SIZE - 1][1] |= (1 << 15); /* end of ring */
}
void
stm32eth_init(void)
{
/* enable clocking of MAC core, ports A, B, C */
RCC_AHB1ENR |= 0x1E000007;
fill_rx_desc();
GPIOA_AFRL |= 0xB000BBBB;
GPIOB_AFRL |= 0x000000BB;
GPIOB_AFRH |= 0x00BBBB0B;
GPIOC_AFRL |= 0x00BBBBB0;
GPIOA_MODER |= 0x000080AA;
GPIOB_MODER |= 0x0AA2000A;
GPIOC_MODER |= 0x00000AA8;
timer_delay(TIMER_TPS / 1000);
ETH_DMATDLAR = (uint32_t)&tx_desc;
ETH_DMARDLAR = (uint32_t)&rx_desc;
ETH_MACCR = (1 << 16) /* disable carrier sense */
| (1 << 3) /* enable transmitter */
| (1 << 2);/* enable receiver */
ETH_DMAOMR = (1 << 21) /* transmit store and forward */
| (1 << 13) /* start transmission */
| (1 << 1);/* start reception */
phy_init();
smi_start_read(1);
}
void
stm32eth_setmac(const uint8_t mac[6])
{
ETH_MACA0LR = *(uint32_t*)mac;
ETH_MACA0HR = *(uint16_t*)(mac + 4);
}
static void
collect_frame(void)
{
int i, remlen;
uint8_t *dst = uip_buf;
remlen = (rx_desc[rx_cur & (RX_RING_SIZE - 1)][0] & 0x3FFF0000) >> 16;
uip_len = remlen;
for (i = rx_first; i <= rx_cur; i++)
{
int len;
len = (i != rx_cur) ? RX_BUF_SIZE : remlen;
memcpy(dst, (void*)rx_buf[i & (RX_RING_SIZE - 1)], len);
dst += len;
remlen -= len;
}
}
static void
reinit_rx_desc(void)
{
unsigned int i;
for (i = rx_cur; i != (rx_first - 1); i--)
{
rx_desc[i & (RX_RING_SIZE - 1)][0] = 1u << 31; /* OWN bit */
}
}
static void
rx_poll(void)
{
uint32_t status;
status = rx_desc[rx_cur & (RX_RING_SIZE - 1)][0];
if (status & (1u << 31)) /* OWN bit */
{
return;
}
if (status & (1 << 9)) /* first segment */
{
rx_first = rx_cur;
}
if (status & (1 << 8)) /* last segment */
{
if ((status & 0x4000F89F) == 0) /* error bits */
{
collect_frame();
}
reinit_rx_desc();
}
rx_cur++;
}
void
stm32eth_poll(void)
{
static timer_value prev;
timer_value now;
now = timer_getval();
if (timer_ticksbetween(prev, now) > TIMER_TPS / 100)
{
link = !!(smi_read_data() & 4);
smi_start_read(1);
prev = now;
}
rx_poll();
}
void
stm32eth_send(void)
{
tx_desc[1] = uip_len;
tx_desc[0] = (1u << 31) /* OWN bit */
| (1 << 29) /* last segment */
| (1 << 28) /* first segment */
| (1 << 21);/* end of ring */
ETH_DMATPDR = 0; /* start transmission */
while (tx_desc[0] & (1u << 31))
{
/* wait until TX descriptor is released */
}
}
bool
stm32eth_link(void)
{
return link;
}
bool
stm32eth_act(void)
{
bool ret;
ret = act;
act = false;
return ret;
}