реклама на сайте
подробности

 
 
> STM32F2 Ethernet
pitt
сообщение Nov 23 2012, 17:22
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 328
Регистрация: 1-06-06
Из: USA
Пользователь №: 17 672



Изучаю документацию и примеры кода. Комментарии непечатные. Не желает ли кто-нибудь поделиться собственной наработкой или дать ссылку на профессиоально сделаный код/пример.

Спасибо


--------------------
Прокричал немой глухому:"...Спасибо за внимание!"
http://www.youtube.com/watch?v=3Nnj4ky4Z_g
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов (1 - 11)
pitt
сообщение Nov 24 2012, 14:25
Сообщение #2


Местный
***

Группа: Участник
Сообщений: 328
Регистрация: 1-06-06
Из: USA
Пользователь №: 17 672



Цитата(pitt @ Nov 23 2012, 12:22) *
Изучаю документацию и примеры кода. Комментарии непечатные. Не желает ли кто-нибудь поделиться собственной наработкой или дать ссылку на профессиоально сделаный код/пример.

Спасибо

Глупый, наверное, вопрос: Когда приложение шлет посылку на МАС, код копирует ее из памяти приложения в буфер DMA, который затем в фоновом режиме копирует дальше в собственно МАС. А почему нельзя DMA изначально направить на память приложения без дополнительной пересылки?

Спасибо.


--------------------
Прокричал немой глухому:"...Спасибо за внимание!"
http://www.youtube.com/watch?v=3Nnj4ky4Z_g
Go to the top of the page
 
+Quote Post
scifi
сообщение Nov 25 2012, 12:47
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(pitt @ Nov 24 2012, 18:25) *
А почему нельзя DMA изначально направить на память приложения без дополнительной пересылки?

Zero-copy transmission? Можно, я так и делаю:

CODE
/**
* @file stm32eth.c
* @brief Драйвер Ethernet для STM32
*/

#include "stm32eth.h"
#include "stm32f2regs.h"
#include "timer.h"
#include "netif/etharp.h"
#include "lwip/mem.h"
#include "lwip/memp.h"
#include "assert_static.h"
#include <string.h>
#include <assert.h>

#define SMI_TMPL 0x00000004 /* sets SMI clock range and PHY address */
#define RX_RING_SIZE 32
#define TX_RING_SIZE 32

struct buf_desc
{
uint32_t volatile status;
uint16_t len[2];
void* ptr[2];
struct pbuf* p[2];
};

static struct netif *mynetif;
static bool link, act;
static bool rx_more; /* if set, need to scan or allocate RX descriptors */
static struct buf_desc tx_desc[TX_RING_SIZE], rx_desc[RX_RING_SIZE];
/* first RX descriptor to check for new frame */
static int rx_current;
/* number of initialized RX descriptors */
static int rx_count;

static bool
smi_busy(void)
{
return !!REGBIT(ETH_MACMIIAR, 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, 0);
smi_write(0x1F, 0x8900);
}

static err_t
low_level_output(struct netif *netif, struct pbuf *p)
{
int i;
uint32_t mask;

while ((ETH_DMASR & 0x00700000) != 0x00600000)
{
/* wait until Tx DMA is suspended */
}
mask = (1u << 31) /* OWN bit */
| (1 << 28); /* first segment */
i = -1;
for (;;)
{
i++;
if (i == TX_RING_SIZE)
{
/* not enough TX descriptors */
return ERR_MEM;
}
tx_desc[i].len[0] = p->len;
tx_desc[i].ptr[0] = p->payload;
p = p->next;
if (p)
{
tx_desc[i].len[1] = p->len;
tx_desc[i].ptr[1] = p->payload;
p = p->next;
if (p)
{
tx_desc[i].status = mask;
mask = (1u << 31); /* OWN bit */
}
else
{
break;
}
}
else
{
tx_desc[i].len[1] = 0;
break;
}
}
mask |= (1 << 21) /* end of ring */
| (1 << 29); /* last segment */
tx_desc[i].status = mask;
REGBIT(ETH_DMASR, 10) = 1; /* reset ETS flag in status register */
ETH_DMATPDR = 0; /* start transmission */
while (REGBIT(ETH_DMASR, 10) == 0)
{
/* wait for data to be copied into Tx FIFO */
}
act = true;
return ERR_OK;
}

/**
* Initialize the Rx buffer descriptor ring by allocating buffers
* and assigning them to descriptors
*/
static void
rx_setup(void)
{
/* Index of first uninitialized Rx buffer descriptor */
int i, rx_start = rx_current + rx_count;
for (i = rx_start; rx_count < RX_RING_SIZE; i++)
{
struct pbuf *p;
int j = i & (RX_RING_SIZE - 1);
p = pbuf_alloc(PBUF_RAW, PBUF_POOL_BUFSIZE, PBUF_POOL);
if (!p)
{
rx_more = true;
break;
}
rx_desc[j].p[0] = p;
rx_desc[j].ptr[0] = p->payload;
rx_desc[j].len[0] = p->len;
if (j == (RX_RING_SIZE - 1))
{
rx_desc[j].len[0] |= (1 << 15);
}
rx_count++;
p = pbuf_alloc(PBUF_RAW, PBUF_POOL_BUFSIZE, PBUF_POOL);
if (p)
{
rx_desc[j].p[1] = p;
rx_desc[j].ptr[1] = p->payload;
rx_desc[j].len[1] = p->len;
}
else
{
rx_desc[j].len[1] = 0;
rx_more = true;
}
rx_desc[j].status = 1u << 31; /* OWN bit */
}
i = rx_current + rx_count;
while (i != rx_start)
{
i--;
rx_desc[i & (RX_RING_SIZE - 1)].status = 1u << 31; /* OWN bit */
}
}

/**
* Discard frame in case of reception error by deallocating buffers
*
* @param first Index of first buffer descriptor to discard
* @param last Index of last buffer descriptor to discard
*/
static void
discard_frame(int first, int last)
{
int i = first - 1;
do
{
i = (i + 1) & (RX_RING_SIZE - 1);
pbuf_free(rx_desc[i].p[0]);
if (rx_desc[i].len[1] != 0)
{
pbuf_free(rx_desc[i].p[1]);
}
}
while (i != last);
/* Keep index in sync with Rx DMA */
rx_current = (last + 1) & (RX_RING_SIZE - 1);
}

/**
* Collect frame by chaining the corresponding pbufs
*
* @param first Index of first buffer descriptor to collect
* @param last Index of last buffer descriptor to collect
* @param lastlen Length of last buffer in chain
*/
static struct pbuf*
collect_frame(int first, int last, int lastlen)
{
unsigned int i;
struct pbuf *h, *t;

/* Trim last buffer, so complete frame length is correct */
if (rx_desc[last].len[1] != 0)
{
t = rx_desc[last].p[1];
pbuf_realloc(t, lastlen);
h = rx_desc[last].p[0];
pbuf_cat(h, t);
t = h;
}
else
{
t = rx_desc[last].p[0];
pbuf_realloc(t, lastlen);
}
/* Walk the buffers from (last - 1) to first */
i = last;
while (i != first)
{
i = (i - 1) & (RX_RING_SIZE - 1);
h = rx_desc[i].p[1];
pbuf_cat(h, t);
t = h;
h = rx_desc[i].p[0];
pbuf_cat(h, t);
t = h;
}
/* Keep index in sync with Rx DMA */
rx_current = (last + 1) & (RX_RING_SIZE - 1);
return t;
}

/**
* Zero-copy reception. Collect DMA'ed data and return frame as pbuf chain.
*
* @return a pbuf filled with the received packet (including MAC header)
* NULL if no received frames
*/
static struct pbuf*
low_level_input(void)
{
int i, n, len0, len, lastlen, status;

i = rx_current;
len = 0;
n = 0;
/* Scan the Rx buffer rescriptor ring */
for (;;)
{
if (i == (rx_current + rx_count))
{
/* Descriptor uninitialized, quit */
return 0;
}
status = rx_desc[i].status;
if (status & (1u << 31))
{
/* Buffer still owned by DMA, quit */
rx_more = false;
return 0;
}
/* Buffer contains frame data, continue */
n++;
len0 = rx_desc[i].len[0] & 0x1FFF;
if (status & (1 << 8))
{
/* Last buffer in frame, finalize */
break;
}
len += len0;
len += rx_desc[i].len[1];
i = (i + 1) & (RX_RING_SIZE - 1);
/* Move on to next buffer in frame */
}
/* Mark processed descriptors as uninitialized */
rx_count -= n;
if ((status & 0x4000F89F) != 0) /* error bits */
{
discard_frame(rx_current, i);
return 0;
}
lastlen = ((status >> 16) & 0x3FFF) - len;
if (lastlen <= len0)
{
if (rx_desc[i].len[1] != 0)
{
pbuf_free(rx_desc[i].p[1]);
rx_desc[i].len[1] = 0;
}
}
else
{
lastlen -= len0;
}
return collect_frame(rx_current, i, lastlen);
}

err_t
stm32eth_init(struct netif *netif)
{
assert_static(IS_PWR_OF_TWO(RX_RING_SIZE));
assert_static(IS_PWR_OF_TWO(TX_RING_SIZE));
mynetif = netif;
netif->name[0] = 'e';
netif->name[1] = 'n';
netif->hwaddr_len = ETHARP_HWADDR_LEN;
netif->mtu = 1500;
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
netif->output = etharp_output;
netif->linkoutput = low_level_output;
/* enable clocking of MAC core, ports A, B, C */
RCC_AHB1ENR |= 0x1E000007;
rx_setup();
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_MACA0LR = *(uint32_t*)netif->hwaddr;
ETH_MACA0HR = *(uint16_t*)(netif->hwaddr + 4);
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_DMABMR |= (2 << 2); /* descriptor skip length = 2 */
ETH_DMAOMR = (1 << 21) /* transmit store and forward */
| (1 << 13) /* start transmission */
| (1 << 1);/* start reception */
phy_init();
smi_start_read(0x1F);
return ERR_OK;
}

void
stm32eth_poll(void)
{
static unsigned int prev;
unsigned int now;
now = timer_get();
if (now - prev > TIMER_TPS / 50)
{
link = !!(smi_read_data() & (1 << 12));
smi_start_read(0x1F);
prev = now;
}
if (REGBIT(ETH_DMASR, 6))
{
/* RS bit set: complete frame received */
REGBIT(ETH_DMASR, 6) = 1; /* clear RS bit */
rx_more = true;
}
if (rx_more)
{
struct pbuf *p;
p = low_level_input();
if (p)
{
ethernet_input(p, mynetif);
}
rx_setup();
ETH_DMARPDR = 0; /* start RX descriptor polling */
}
}

bool
stm32eth_link(void)
{
return link;
}

bool
stm32eth_act(void)
{
bool ret;
ret = act;
act = false;
return ret;
}
Go to the top of the page
 
+Quote Post
AlexandrY
сообщение Nov 25 2012, 20:12
Сообщение #4


Ally
******

Группа: Модераторы
Сообщений: 6 232
Регистрация: 19-01-05
Пользователь №: 2 050



Цитата(pitt @ Nov 24 2012, 16:25) *
Глупый, наверное, вопрос: Когда приложение шлет посылку на МАС, код копирует ее из памяти приложения в буфер DMA, который затем в фоновом режиме копирует дальше в собственно МАС. А почему нельзя DMA изначально направить на память приложения без дополнительной пересылки?

Спасибо.


Возможно оптимизировали по скорости.
DMA из некоторых областей памяти очень медленно работает и замедляет выполнение программы при этом.
Go to the top of the page
 
+Quote Post
pitt
сообщение Nov 25 2012, 21:04
Сообщение #5


Местный
***

Группа: Участник
Сообщений: 328
Регистрация: 1-06-06
Из: USA
Пользователь №: 17 672



Цитата(AlexandrY @ Nov 25 2012, 15:12) *
Возможно оптимизировали по скорости.
DMA из некоторых областей памяти очень медленно работает и замедляет выполнение программы при этом.

Но ведь последующее копирование в ту же самую память приложения тоже стоит времени...Непонятно.


--------------------
Прокричал немой глухому:"...Спасибо за внимание!"
http://www.youtube.com/watch?v=3Nnj4ky4Z_g
Go to the top of the page
 
+Quote Post
scifi
сообщение Nov 26 2012, 10:34
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(pitt @ Nov 26 2012, 01:04) *
Но ведь последующее копирование в ту же самую память приложения тоже стоит времени...Непонятно.

Упрощение кода. Без вариантов.

Update:
Вообще-то есть варианты. EMAC DMA не может вытаскивать данные из on-chip flash. Копирование данных перед отправкой снимает это ограничение.
Go to the top of the page
 
+Quote Post
pitt
сообщение Dec 8 2012, 04:24
Сообщение #7


Местный
***

Группа: Участник
Сообщений: 328
Регистрация: 1-06-06
Из: USA
Пользователь №: 17 672



Не запускается МАС. Ситуация следущая: разговариваю с PHY, есть линк(autoneg) на 100/fd; дескриптор передачи приготовлен. Запускаю DMA. пока не сбросится TDESC0.31 OWN читаю ETH->DMADBGR(почему-то, у них он записан как ETH->RESERVED1[1], там все нули и ничего не происходит. DMA заканчивает работу, suspends. Линк стоит, МАС в IDLE... Советы? Предложения? Примеры СОБСТВЕННОГО кода? Кстати, а как МАС узнает длину фрейма? Length/Type если больше 1536 уже не длина, а тип, которых разнообразие, с разными заголовками и знать их все МАС попросту не может... Цитата из RM0033
Цитата
Bit 21TSF: Transmit store and forward
When this bit is set, transmission starts when a full frame resides in the Transmit FIFO. When this bit is set, the TTC values specified by the ETH_DMAOMR register bits [16:14] are ignored.


Спасибо.


--------------------
Прокричал немой глухому:"...Спасибо за внимание!"
http://www.youtube.com/watch?v=3Nnj4ky4Z_g
Go to the top of the page
 
+Quote Post
Allregia
сообщение Dec 8 2012, 09:05
Сообщение #8


Профессионал
*****

Группа: Свой
Сообщений: 1 047
Регистрация: 28-06-07
Из: Israel
Пользователь №: 28 763



Цитата(AlexandrY @ Nov 25 2012, 22:12) *
Возможно оптимизировали по скорости.
DMA из некоторых областей памяти очень медленно работает и замедляет выполнение программы при этом.


Из каких именно областей?
Go to the top of the page
 
+Quote Post
pitt
сообщение Dec 8 2012, 13:00
Сообщение #9


Местный
***

Группа: Участник
Сообщений: 328
Регистрация: 1-06-06
Из: USA
Пользователь №: 17 672



Цитата(Allregia @ Dec 8 2012, 04:05) *
Из каких именно областей?

Сильно сомневаюсь...0х2000.......
А не затруднит ли поместить небольшой фрейм полностью...У меня подозрение, что МАС не воспринимает мой. Я НЕ использую IP. Все свое: код, апликации, протоколы...


--------------------
Прокричал немой глухому:"...Спасибо за внимание!"
http://www.youtube.com/watch?v=3Nnj4ky4Z_g
Go to the top of the page
 
+Quote Post
pitt
сообщение Dec 8 2012, 22:50
Сообщение #10


Местный
***

Группа: Участник
Сообщений: 328
Регистрация: 1-06-06
Из: USA
Пользователь №: 17 672



Не понимаю что тут написано:
Цитата
After the EOF is transferred to the MAC core, the core completes normal transmission and then gives the status of transmission back to the DMA. If a normal collision (in Half-duplex mode) occurs during transmission, the MAC core makes the transmit status valid, then accepts and drops all further data until the next SOF is received. The same frame should be retransmitted from SOF on observing a Retry request (in the Status) from the MAC. The MAC issues an underflow status if the data are not provided continuously during the transmission. During the normal transfer of a frame, if the MAC receives an SOF without getting an EOF for the previous frame, then the SOF is ignored and the new frame is considered as the continuation of the previous frame.
RM0033 Doc ID 15403 Rev 5 p.826/1334
SOF == SFD? Если нет то что? А что у них EOF?

Сообщение отредактировал pitt - Dec 9 2012, 20:45


--------------------
Прокричал немой глухому:"...Спасибо за внимание!"
http://www.youtube.com/watch?v=3Nnj4ky4Z_g
Go to the top of the page
 
+Quote Post
vsk
сообщение Dec 10 2012, 10:54
Сообщение #11


Участник
*

Группа: Участник
Сообщений: 18
Регистрация: 11-01-08
Пользователь №: 33 988



Походу здесь UDP посылка обсуждается, OSI - модель прочтите заново...
Go to the top of the page
 
+Quote Post
pitt
сообщение Dec 10 2012, 12:26
Сообщение #12


Местный
***

Группа: Участник
Сообщений: 328
Регистрация: 1-06-06
Из: USA
Пользователь №: 17 672



Цитата(vsk @ Dec 10 2012, 05:54) *
Походу здесь UDP посылка обсуждается, OSI - модель прочтите заново...
Это, извините, описание МАС: Media Access Controller.


--------------------
Прокричал немой глухому:"...Спасибо за внимание!"
http://www.youtube.com/watch?v=3Nnj4ky4Z_g
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 20th July 2025 - 11:41
Рейтинг@Mail.ru


Страница сгенерированна за 0.01488 секунд с 7
ELECTRONIX ©2004-2016