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

 
 
> LPC1788 Ethernet DMA драйвер - прерывания, Не работают прерывания от EMAC
Cosmojam
сообщение Jul 17 2012, 10:44
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 311
Регистрация: 12-01-11
Из: Калининград (Koenigsberg)
Пользователь №: 62 182



Помогите осилить эзернет на LPC1788
За основу взят пример с FreeRTOS+LwIP для LPC1768 вместе с драйвером эзернет (судя по даташиту модули emac идентичны за исключением поддерки MII, но у меня всё равно используется RMII).
Проблема следующая: инициализация MAC и PHY проходит успешно, линк поднимается на 100мбит полный дуплекс, зелёный диод мыргает при получении широковещательного трафика, на выводах PHY RXD[0:1] присутствуют данные при приёме. Но не генерируется прерывание от EMAC ни на приём ни на передачу.
Инициализация EMAC:
CODE
Status EMAC_Init(EMAC_CFG_Type *EMAC_ConfigStruct)
{
/* Initialize the EMAC Ethernet controller. */
int32_t regv,tout, tmp;

/* Set up clock and power for Ethernet module */
CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCENET, ENABLE);

/* Reset all EMAC internal modules */
LPC_EMAC->MAC1 = EMAC_MAC1_RES_TX | EMAC_MAC1_RES_MCS_TX | EMAC_MAC1_RES_RX |
EMAC_MAC1_RES_MCS_RX | EMAC_MAC1_SIM_RES | EMAC_MAC1_SOFT_RES;

LPC_EMAC->Command = EMAC_CR_REG_RES | EMAC_CR_TX_RES | EMAC_CR_RX_RES |
EMAC_CR_PASS_RUNT_FRM;

/* A short delay after reset. */
vTaskDelay( 2 );

/* Initialize MAC control registers. */
LPC_EMAC->MAC1 = EMAC_MAC1_PASS_ALL;
LPC_EMAC->MAC2 = EMAC_MAC2_CRC_EN | EMAC_MAC2_PAD_EN;
LPC_EMAC->MAXF = EMAC_ETH_MAX_FLEN;

/*
* Find the clock that close to desired target clock
*/
tmp = CLKPWR_GetCLK(CLKPWR_CLKTYPE_CPU) / EMAC_MCFG_MII_MAXCLK;
for (tout = 0; tout < sizeof (EMAC_clkdiv); tout++){
if (EMAC_clkdiv[tout] >= tmp) break;
}
tout++;

// Write to MAC configuration register and reset
LPC_EMAC->MCFG = EMAC_MCFG_CLK_SEL(tout) | EMAC_MCFG_RES_MII;

// release reset
LPC_EMAC->MCFG &= ~(EMAC_MCFG_RES_MII);
LPC_EMAC->CLRT = EMAC_CLRT_DEF;
LPC_EMAC->IPGR = EMAC_IPGR_P2_DEF;

/* Enable Reduced MII interface. */
LPC_EMAC->Command = EMAC_CR_RMII | EMAC_CR_PASS_RUNT_FRM;

/* A short delay after reset. */
vTaskDelay( 2 );

LPC_EMAC->SUPP = 0;

/* Put the DP83848C in reset mode */
write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_BMCR_RESET);

/* Wait for hardware reset to end. */
for (tout = EMAC_PHY_RESP_TOUT; tout; tout--) {
regv = read_PHY (EMAC_PHY_REG_BMCR);
if (!(regv & (EMAC_PHY_BMCR_RESET | EMAC_PHY_BMCR_POWERDOWN))) {
/* Reset complete, device not Power Down. */
break;
}
if (tout == 0){
// Time out, return ERROR
return (ERROR);
}
vTaskDelay( 2 );
}

// Set PHY mode
if (EMAC_SetPHYMode(EMAC_ConfigStruct->Mode) < 0){
return (ERROR);
}

// Set EMAC address
setEmacAddr(EMAC_ConfigStruct->pbEMAC_Addr);

/* Initialize Tx and Rx DMA Descriptors */
rx_descr_init ();
tx_descr_init ();

// Set Receive Filter register: enable broadcast and multicast
LPC_EMAC->RxFilterCtrl = EMAC_RFC_MCAST_EN | EMAC_RFC_BCAST_EN | EMAC_RFC_PERFECT_EN;

/* Enable Rx Done and Tx Done interrupt for EMAC */
LPC_EMAC->IntEnable = EMAC_INT_RX_DONE | EMAC_INT_TX_DONE;

/* Reset all interrupts */
LPC_EMAC->IntClear = 0xFFFF;

/* Enable receive and transmit mode of MAC Ethernet core */
LPC_EMAC->Command |= (EMAC_CR_RX_EN | EMAC_CR_TX_EN);
LPC_EMAC->MAC1 |= EMAC_MAC1_REC_EN;

return SUCCESS;
}

Инициализация дескрипторов DMA
CODE
/** Rx Descriptor data array */
static volatile RX_Desc Rx_Desc[EMAC_NUM_RX_FRAG];

/** Rx Status data array - Must be 8-Byte aligned */
static volatile __attribute__ ((aligned (8))) RX_Stat Rx_Stat[EMAC_NUM_RX_FRAG];

/** Tx Descriptor data array */
static volatile TX_Desc Tx_Desc[EMAC_NUM_TX_FRAG];
/** Tx Status data array */
static volatile TX_Stat Tx_Stat[EMAC_NUM_TX_FRAG];

#define EMAC_ETH_MAX_FLEN 1536

typedef uint32_t xEMACRxBuffer_t[ EMAC_NUM_RX_FRAG ][ EMAC_ETH_MAX_FLEN >> 2 ];
typedef uint32_t xEMACTxBuffer_t[ EMAC_NUM_TX_FRAG ][ EMAC_ETH_MAX_FLEN >> 2 ];

static void rx_descr_init (void)
{
/* Initialize Receive Descriptor and Status array. */
uint32_t i;
extern void *pvApplicationGetEMACRxBufferAddress( void );
xEMACRxBuffer_t *rx_buf;

rx_buf = ( xEMACRxBuffer_t * ) pvApplicationGetEMACRxBufferAddress();
for (i = 0; i < EMAC_NUM_RX_FRAG; i++) {
Rx_Desc[i].Packet = (uint32_t)&(*rx_buf)[i];
Rx_Desc[i].Ctrl = EMAC_RCTRL_INT | (EMAC_ETH_MAX_FLEN - 1);
Rx_Stat[i].Info = 0xFFFFFFFF;
Rx_Stat[i].HashCRC = 0xFFFFFFFF;
}

/* Set EMAC Receive Descriptor Registers. */
LPC_EMAC->RxDescriptor = (uint32_t)&Rx_Desc[0];
LPC_EMAC->RxStatus = (uint32_t)&Rx_Stat[0];
LPC_EMAC->RxDescriptorNumber = EMAC_NUM_RX_FRAG - 1;

/* Rx Descriptors Point to 0 */
LPC_EMAC->RxConsumeIndex = 0;
}

static void tx_descr_init (void) {
/* Initialize Transmit Descriptor and Status array. */
uint32_t i;
extern void *pvApplicationGetEMACTxBufferAddress( void );
xEMACTxBuffer_t *tx_buf;

tx_buf = ( xEMACTxBuffer_t * ) pvApplicationGetEMACTxBufferAddress();
for (i = 0; i < EMAC_NUM_TX_FRAG; i++) {
Tx_Desc[i].Packet = (uint32_t)&(*tx_buf)[i];
Tx_Desc[i].Ctrl = 0xFFFFFFFF;
Tx_Stat[i].Info = 0xFFFFFFFF;
}

/* Set EMAC Transmit Descriptor Registers. */
LPC_EMAC->TxDescriptor = (uint32_t)&Tx_Desc[0];
LPC_EMAC->TxStatus = (uint32_t)&Tx_Stat[0];
LPC_EMAC->TxDescriptorNumber = EMAC_NUM_TX_FRAG - 1;

/* Tx Descriptors Point to 0 */
LPC_EMAC->TxProduceIndex = 0;
}


void *pvApplicationGetEMACTxBufferAddress(void)
{
static volatile xEMACTxBuffer_t txb __attribute__ ((aligned (4)));
return (void *)txb;
}

void *pvApplicationGetEMACRxBufferAddress(void)
{

static volatile xEMACRxBuffer_t rxb __attribute__ ((aligned (4)));
return (void *)rxb;
}

Инициализация дескрипторов тоже вроде как проходит успешно, отладчиком вижу правильные адреса буферов приёма/передачи в регистрах EMAC. Прерывания RxDoneInt и TxDoneInt включены. Прерывание от EMAC в NVIC разрешено. Всё выглядит верно настроенным, но прерываний от EMAC нет вообще. Тот же самый код работает на LPC1768 с такой же PHY (KS8721B), прерывание бегают, LwIP работает. А тут вообще глухо, будто прерывания запрещены или он просто не принимает/не передаёт ничего, но на выводах RXD[0:1] чётко видны импульсы при приёме ARP пакетов. Пробовал подбирать чатсоту RMII от 2.5 до 15 МГц. Пробовал менять частоту проца от 80 до 120МГц. Никаких результатов.
Готовый порт http://www.lpcware.com/content/project/lig...etworking-stack тоже запустить не удалось, но по-правде говоря не сильно углублялся в него - слишком наворочено. Внимательно посмотрел как там инициализация EMAC сделана, сравнил со своей - вроде всё так же. Кто сталкивался с эзернетом на этом проце подскажите что-нибудь вроде рабочиего кода инициалицации EMAC sm.gif

Сообщение отредактировал IgorKossak - Jul 17 2012, 19:53
Причина редактирования: [codebox] для длинного кода!!!


--------------------
typedef enum { no, yes, maybe } bool; | блог тут
Go to the top of the page
 
+Quote Post
2 страниц V   1 2 >  
Start new topic
Ответов (1 - 15)
DmitryM
сообщение Jul 17 2012, 12:43
Сообщение #2


Знающий
****

Группа: Свой
Сообщений: 583
Регистрация: 7-06-06
Из: Таганрог
Пользователь №: 17 840



Цитата(Cosmojam @ Jul 17 2012, 14:44) *
Пробовал подбирать частоту RMII от 2.5 до 15 МГц.

А разве частота RMII не задается PHY равной 50МГц? Или речь идет о MDC, MDIO?
Go to the top of the page
 
+Quote Post
Cosmojam
сообщение Jul 17 2012, 13:08
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 311
Регистрация: 12-01-11
Из: Калининград (Koenigsberg)
Пользователь №: 62 182



Цитата(DmitryM @ Jul 17 2012, 15:43) *
А разве частота RMII не задается PHY равной 50МГц? Или речь идет о MDC, MDIO?

Да, о MDC, попутал чуток sm.gif
Цитата
5:2
CLOCK SELECT
This field is used by the clock divide logic in creating the MII Management Clock
(MDC) which IEEE 802.3u defines to be no faster than 2.5 MHz. Some PHYs
support clock rates up to 12.5 MHz, however. The AHB bus clock (HCLK) is divided
by the specified amount. Refer to Table 160 below for the definition of values for this
field.


Насчёт отсутствия прерываний я соврал. После сброса и инициализации EMAC+PHY всего одно прерывание происходит если что-то было принято. Т.е. ставлю брейкпоинт на ENET_IRQHandler, запускаю программу - тишина. С компьютера пробую пинговать плату (на сетевом уровне широковещательный ARP запроспроходит) - срабатывает прерывание, в регистре IntStatus подняты флаги RxErrorInt и RxFinishedInt. Обработчик прерывания их не обрабатывает, а просто сбрасывает. Больше после этого никаких прерываний не происходит. Причём проверил на LPC1768 там тоже постоянно встаёт флагRxErrorInt, но всем пофиг и с ним хорошо работает. Значит приём всё же работает, а косяк по-видимому с дескрипторами DMA.

Попробовал запустить пример EasyWeb из NXP-шной библиотеки. Заработало. Похоже есть хоть какая-то зацепка.



--------------------
typedef enum { no, yes, maybe } bool; | блог тут
Go to the top of the page
 
+Quote Post
Cosmojam
сообщение Jul 17 2012, 15:53
Сообщение #4


Местный
***

Группа: Свой
Сообщений: 311
Регистрация: 12-01-11
Из: Калининград (Koenigsberg)
Пользователь №: 62 182



С дескрипторами вот что происходит:
RxProduceIndex достигает 3 (максимум 4 фрагмента) и на этом останавливается, RxConsumeIndex стоит на 0. Буфер, определённый в дескрипторе приёма остаётся пустым
TxProduceIndex останавливается на 1, TxConsumeIndex в 0. В буфере передачи появляется FFFF0012 13101511 08060001 08000604 00010012 13101511 C0A801C8 00000000 0000C0A8 01C80000 00000000 и дальше нули, похоже на один фрейм, 001213101511 - MAC адрес, с остальной структурой не разбирался.
Получается что EMAC принимает фрагменты, инкрементирует индекс в дескрипторе, но не пишет ничего в буфер и потому не поднимает флаг прерывания.


--------------------
typedef enum { no, yes, maybe } bool; | блог тут
Go to the top of the page
 
+Quote Post
andrewlekar
сообщение Jul 18 2012, 05:17
Сообщение #5


Знающий
****

Группа: Участник
Сообщений: 837
Регистрация: 8-02-07
Пользователь №: 25 163



У меня на LPC1768 была какая-то загвоздка с прерываниями и я оставил тупо поллинг дескрипторов. Может тут также сделать?
Go to the top of the page
 
+Quote Post
Cosmojam
сообщение Jul 18 2012, 08:39
Сообщение #6


Местный
***

Группа: Свой
Сообщений: 311
Регистрация: 12-01-11
Из: Калининград (Koenigsberg)
Пользователь №: 62 182



Поллинг не поможет - проблема с самими дескрипторами, похоже, а не с прерываниями. В статусные дескрипторы ничего не записывается при приёме/передаче. Они как инициализируются в 0 так и остаются, НО RxProduceIndex инкрементируется будто всё ОК. Это не соответствует инфе из даташита:
Цитата
After receiving a fragment, the Rx DMA manager writes status information back to the StatusInfo and StatusHashCRC words of the status. The Ethernet block writes the size in bytes of a descriptor’s fragment buffer in the RxSize field of the Status word. The value of the RxProduceIndex is only updated after the fragment data and the fragment status information has been committed to memory, which is checked by an internal tag protocol in the memory interface.

Т.е. RxProduceIndex инкрементируется только после успешной записи и проверки данных записанных в буфер и статусный дескриптор. Но у меня ничего не пишется ни в буфер ни в статус, а RxProduceIndex инкрементиуется пока не достигнет количество фрагментов-1 и выставляет прерывание RxFinishedInt. На этом всё останавливается.


--------------------
typedef enum { no, yes, maybe } bool; | блог тут
Go to the top of the page
 
+Quote Post
andrewlekar
сообщение Jul 18 2012, 09:53
Сообщение #7


Знающий
****

Группа: Участник
Сообщений: 837
Регистрация: 8-02-07
Пользователь №: 25 163



Ну тогда проверяйте память, адреса, указатели.
Go to the top of the page
 
+Quote Post
Cosmojam
сообщение Jul 18 2012, 10:26
Сообщение #8


Местный
***

Группа: Свой
Сообщений: 311
Регистрация: 12-01-11
Из: Калининград (Koenigsberg)
Пользователь №: 62 182



[CENSORED] Нашёл причину, разместив буферы и дескрипторы в RamPeriph32 которая начинается с 0x20000000. Заработало! Но какого чёрта не работает если размещать их в RamLoc64? Где про это написано? Причём в официальном порте LwIP том что на lpcware есть примеры с конфигурацией где эти буферы размещаются во внешней SDRAM, что мне ещё предстоит. Пойду перечитывать даташит

Сообщение отредактировал IgorKossak - Jul 18 2012, 13:17


--------------------
typedef enum { no, yes, maybe } bool; | блог тут
Go to the top of the page
 
+Quote Post
ReAl
сообщение Jul 18 2012, 16:53
Сообщение #9


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Detailed block diagram (Fig.2 LPC178x/177x block diagram, CPU and buses) -- Eth 10/100 MAC (и не только он) не имеет выхода на шину System RAM / Boot ROM
А на Memory Controller имеет.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
Cosmojam
сообщение Jul 18 2012, 18:44
Сообщение #10


Местный
***

Группа: Свой
Сообщений: 311
Регистрация: 12-01-11
Из: Калининград (Koenigsberg)
Пользователь №: 62 182



Спасибо пребольшое!
Кстати, нашёл где написано про это http://www.lpcware.com/content/project/lig...ffer-management курсивом
Цитата
Note: For the LPC17xx, the descriptors and buffers must be located only in peripheral RAM or external memory. For the LPC18xx/43xx, descriptors and buffers can be located anywhere.

Только у LPC1768 можно

Сообщение отредактировал Cosmojam - Jul 18 2012, 20:59


--------------------
typedef enum { no, yes, maybe } bool; | блог тут
Go to the top of the page
 
+Quote Post
romas2010
сообщение Oct 1 2012, 07:26
Сообщение #11


Участник
*

Группа: Участник
Сообщений: 63
Регистрация: 25-11-11
Пользователь №: 68 515



Цитата(Cosmojam @ Jul 18 2012, 22:44) *
Спасибо пребольшое!
Кстати, нашёл где написано про это http://www.lpcware.com/content/project/lig...ffer-management курсивом

Только у LPC1768 можно


Да,столкнулся с такой же петрушкой на 1788...Дело в том,что в примере дескрипторы уже описываются расположенными в AHB RAM.Я думал,что это не важно,сделал по-своему,разместив их в обычной RAM.
потом сделал как в этом примере,и заработало,причем как и в прерывании,так и без,просто в опросе.Тут другое непонятно.NXP похоже,так и не устранили глюк-если объявляешь NUM_RX_FRAG=1 или
NUM_ТX_FRAG=1.то есть типа,ты отпраил пакет,сделал условно TxProduce++,однако он не увеличивается,а на втором проходе этой же командой (TxProduce++)он сразу увеличивается на 2. Таким образом получается,что надо минимум NUM_RX_FRAG=2 и NUM_ТX_FRAG=2 и что 3 Кбайта памяти просто тратится впустую...
Go to the top of the page
 
+Quote Post
theBMV
сообщение Oct 3 2012, 05:55
Сообщение #12


Частый гость
**

Группа: Свой
Сообщений: 131
Регистрация: 14-10-08
Из: г. Королев
Пользователь №: 40 940



Цитата(romas2010 @ Oct 1 2012, 11:26) *
Тут другое непонятно.NXP похоже,так и не устранили глюк-если объявляешь NUM_RX_FRAG=1 или
NUM_ТX_FRAG=1.то есть типа,ты отпраил пакет,сделал условно TxProduce++,однако он не увеличивается,а на втором проходе этой же командой (TxProduce++)он сразу увеличивается на 2. Таким образом получается,что надо минимум NUM_RX_FRAG=2 и NUM_ТX_FRAG=2 и что 3 Кбайта памяти просто тратится впустую...


Нет, не тратится. Это происходит только первый раз после сброса. Просто после инициализации отошли пару пустых пакетов sm.gif В ERRATA этот момент описан

Сообщение отредактировал theBMV - Oct 3 2012, 05:56
Go to the top of the page
 
+Quote Post
Kevlar
сообщение Dec 5 2012, 20:40
Сообщение #13





Группа: Новичок
Сообщений: 1
Регистрация: 4-12-12
Пользователь №: 74 702



Немного не из этой темы, но связано с ней. Я новичок в ARM. И у меня проблема с работой ks8721 и LPC1778. Как я понял из этой ветки форума, проблема в размещении дескрипторов в RAM. Вопрос каким образом явно разместить их там.
Go to the top of the page
 
+Quote Post
romas2010
сообщение Dec 6 2012, 18:04
Сообщение #14


Участник
*

Группа: Участник
Сообщений: 63
Регистрация: 25-11-11
Пользователь №: 68 515



Цитата(Kevlar @ Dec 5 2012, 23:40) *
Немного не из этой темы, но связано с ней. Я новичок в ARM. И у меня проблема с работой ks8721 и LPC1778. Как я понял из этой ветки форума, проблема в размещении дескрипторов в RAM. Вопрос каким образом явно разместить их там.

Скачиваешь с http://www.nxp.com/products/microcontrolle...rtex_m3/lpc1700 файл ...PDL.zip .Это типа примеры.Изучаешь файлы ...EMAC.c и ...EMAC.h там можно понять,что и как и более того ks8721 там тоже инициализируется
Go to the top of the page
 
+Quote Post
Cosmojam
сообщение Dec 6 2012, 18:31
Сообщение #15


Местный
***

Группа: Свой
Сообщений: 311
Регистрация: 12-01-11
Из: Калининград (Koenigsberg)
Пользователь №: 62 182



Цитата(Kevlar @ Dec 5 2012, 23:40) *
Немного не из этой темы, но связано с ней. Я новичок в ARM. И у меня проблема с работой ks8721 и LPC1778. Как я понял из этой ветки форума, проблема в размещении дескрипторов в RAM. Вопрос каким образом явно разместить их там.

Это от компилятора (линкера) зависит.
Что за проблема по-точнее? Какой компилятор, IDE?


--------------------
typedef enum { no, yes, maybe } bool; | блог тут
Go to the top of the page
 
+Quote Post
SyncLair
сообщение Dec 6 2012, 20:33
Сообщение #16


Местный
***

Группа: Свой
Сообщений: 209
Регистрация: 6-01-12
Пользователь №: 69 197



Цитата(Kevlar @ Dec 6 2012, 00:40) *
Немного не из этой темы, но связано с ней. Я новичок в ARM. И у меня проблема с работой ks8721 и LPC1778. Как я понял из этой ветки форума, проблема в размещении дескрипторов в RAM. Вопрос каким образом явно разместить их там.

Нужно применить скрипт линкера, который автоматом их закидывает по нужному адресу, если у тебя gcc, могу помочь с компиляцией.


--------------------
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 21st July 2025 - 03:29
Рейтинг@Mail.ru


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