How to properly disable interrupts for endpoint?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

How to properly disable interrupts for endpoint?

Jump to solution
1,227 Views
dark0711
Contributor III

Добрый день. Использую микроконтроллер lpc54606J512 , KSDK 2.3.0 (released 2017-11-16), IDE Keil 5.24a.
Есть USB устройство с 2-мя интерфейсами, 1 CCID(Endpoint 0x01 0x81), 2 Mass Storage(Endpoint 0x02 0x82).

Mass Storage обрабатывается сразу в прерывании.
CCID в основном потоке, по флагу.

Проблема в том что CCID работает очень медленно, как я понял проблема в слишком часты прерываниях USB(видимо обрабатываться все NAK). Для устранения этой проблемы отключаю endpoint когда они не используются через регистр INTEN и тогда работа CCID значительно ускоряется.
При полном приёме или отправке данных ставлю lpc3511IpState->registerBase->INTEN |= (uint32_t) ((0x01u << endpointIndex))
И когда сново требуется принять или отправить данные сново разрешаю прерывания через lpc3511IpState->registerBase->INTEN |= (uint32_t) (0x01u << endpointIndex);.

Но при большой нагрузке на Mass Storage, ССID в случайный момент времени перестает отвечать, а конкретнее то зависает IN точка.

Подскажите как мне правильно избегать лишних прерываний когда я не использую endpoint?

Good afternoon. I use microcontroller lpc54606J512, KSDK 2.3.0 (released 2017-11-16), IDE Keil 5.24a.
There is a USB device with 2 interfaces, 1 CCID (Endpoint 0x01 0x81), 2 Mass Storage (Endpoint 0x02 0x82).

Mass Storage is processed immediately in an interrupt.
CCID in the main thread, by the flag.

The problem is that CCID works very slowly, as I understood the problem in the USB interrupts too frequent (apparently all NAKs are processed). To solve this problem, I disable the endpoint when they are not used through the INTEN register and then the CCID operation is significantly accelerated.
At full reception or data sending I put lpc3511IpState-> registerBase-> INTEN | = (uint32_t) ((0x01u << endpointIndex))
And when I need to accept or send data again, I resolve the interrupts again through lpc3511IpState-> registerBase-> INTEN | = (uint32_t) (0x01u << endpointIndex) ;.

But with a heavy load on Mass Storage, the CCID stops responding at a random time, and more specifically the IN point hangs.

Tell me how to correctly avoid unnecessary interrupts when I do not use endpoint?

Tags (2)
0 Kudos
1 Solution
945 Views
dark0711
Contributor III

Итак ошибка была в пропуске прерывания. Исправил следующим способом.
Когда принял данные то отключаю конечную точку до следующего запроса на отправку или приём

#if (defined USB_DEVICE_IP3511_DOUBLE_BUFFER_ENABLE) && (USB_DEVICE_IP3511_DOUBLE_BUFFER_ENABLE)

#else
if((endpointIndex >> 1U) != USB_CONTROL_ENDPOINT)
{
USB_LPC3511IP_ENDPOINT_SET_ENDPOINT_AND(lpc3511IpState, endpointIndex, 0, ~(USB_LPC3511IP_ENDPOINT_ACTIVE_MASK));
lpc3511IpState->registerBase->INTEN &= (uint32_t) (~(0x01u << endpointIndex));
while(((lpc3511IpState->registerBase->INTEN & (0x01u << endpointIndex)) >> endpointIndex) != 0)
{
}
lpc3511IpState->registerBase->EPSKIP |= (0x01U << endpointIndex);
while(lpc3511IpState->registerBase->EPSKIP & (0x01U << endpointIndex))
{
}
}
#endif

При запросе на отправку или приём разрешаю

if((endpointIndex >> 1U) != USB_CONTROL_ENDPOINT)
{
lpc3511IpState->registerBase->INTEN |= (uint32_t) (0x01u << endpointIndex);
while(((lpc3511IpState->registerBase->INTEN & (0x01u << endpointIndex)) >> endpointIndex) == 0)
{
}
}

Но всеравно можно пропустить прерывание и нужно обязательно смотреть INTSTAT без маски INTEN в функции USB_DeviceLpcIp3511IsrFunction
interruptStatus = lpc3511IpState->registerBase->INTSTAT;
lpc3511IpState->registerBase->INTSTAT = interruptStatus;
//interruptStatus &= lpc3511IpState->registerBase->INTEN;

Такой вот костыль

Исходный код ниже

So the error was in the interruption pass. Corrected in the following way.
When I accepted the data, I turn off the endpoint until the next request to send or receive

        

#if (defined USB_DEVICE_IP3511_DOUBLE_BUFFER_ENABLE) && (USB_DEVICE_IP3511_DOUBLE_BUFFER_ENABLE)

        #else
        if ((endpointIndex >> 1U)! = USB_CONTROL_ENDPOINT)
        {
            USB_LPC3511IP_ENDPOINT_SET_ENDPOINT_AND (lpc3511IpState, endpointIndex, 0, ~ (USB_LPC3511IP_ENDPOINT_ACTIVE_MASK));
            lpc3511IpState-> registerBase-> INTEN & = (uint32_t) (~ (0x01u << endpointIndex));
            while (((lpc3511IpState-> registerBase-> INTEN & (0x01u << endpointIndex)) >> endpointIndex)! = 0)
            {
            }
            lpc3511IpState-> registerBase-> EPSKIP | = (0x01U << endpointIndex);
            while (lpc3511IpState-> registerBase-> EPSKIP & (0x01U << endpointIndex))
            {
            }
        }
        #endif
        
When requesting to send or receive I authorize

    if ((endpointIndex >> 1U)! = USB_CONTROL_ENDPOINT)
    {
        lpc3511IpState-> registerBase-> INTEN | = (uint32_t) (0x01u << endpointIndex);
        while (((lpc3511IpState-> registerBase-> INTEN & (0x01u << endpointIndex)) >> endpointIndex) == 0)
        {
        }
    }
    
But it's possible to skip the interrupt and it's necessary to watch INTSTAT without the INTEN mask in the function USB_DeviceLpcIp3511IsrFunction
    interruptStatus = lpc3511IpState-> registerBase-> INTSTAT;
    lpc3511IpState-> registerBase-> INTSTAT = interruptStatus;
    // interruptStatus & = lpc3511IpState-> registerBase-> INTEN;
    
Such a crutch

View solution in original post

0 Kudos
2 Replies
946 Views
dark0711
Contributor III

Итак ошибка была в пропуске прерывания. Исправил следующим способом.
Когда принял данные то отключаю конечную точку до следующего запроса на отправку или приём

#if (defined USB_DEVICE_IP3511_DOUBLE_BUFFER_ENABLE) && (USB_DEVICE_IP3511_DOUBLE_BUFFER_ENABLE)

#else
if((endpointIndex >> 1U) != USB_CONTROL_ENDPOINT)
{
USB_LPC3511IP_ENDPOINT_SET_ENDPOINT_AND(lpc3511IpState, endpointIndex, 0, ~(USB_LPC3511IP_ENDPOINT_ACTIVE_MASK));
lpc3511IpState->registerBase->INTEN &= (uint32_t) (~(0x01u << endpointIndex));
while(((lpc3511IpState->registerBase->INTEN & (0x01u << endpointIndex)) >> endpointIndex) != 0)
{
}
lpc3511IpState->registerBase->EPSKIP |= (0x01U << endpointIndex);
while(lpc3511IpState->registerBase->EPSKIP & (0x01U << endpointIndex))
{
}
}
#endif

При запросе на отправку или приём разрешаю

if((endpointIndex >> 1U) != USB_CONTROL_ENDPOINT)
{
lpc3511IpState->registerBase->INTEN |= (uint32_t) (0x01u << endpointIndex);
while(((lpc3511IpState->registerBase->INTEN & (0x01u << endpointIndex)) >> endpointIndex) == 0)
{
}
}

Но всеравно можно пропустить прерывание и нужно обязательно смотреть INTSTAT без маски INTEN в функции USB_DeviceLpcIp3511IsrFunction
interruptStatus = lpc3511IpState->registerBase->INTSTAT;
lpc3511IpState->registerBase->INTSTAT = interruptStatus;
//interruptStatus &= lpc3511IpState->registerBase->INTEN;

Такой вот костыль

Исходный код ниже

So the error was in the interruption pass. Corrected in the following way.
When I accepted the data, I turn off the endpoint until the next request to send or receive

        

#if (defined USB_DEVICE_IP3511_DOUBLE_BUFFER_ENABLE) && (USB_DEVICE_IP3511_DOUBLE_BUFFER_ENABLE)

        #else
        if ((endpointIndex >> 1U)! = USB_CONTROL_ENDPOINT)
        {
            USB_LPC3511IP_ENDPOINT_SET_ENDPOINT_AND (lpc3511IpState, endpointIndex, 0, ~ (USB_LPC3511IP_ENDPOINT_ACTIVE_MASK));
            lpc3511IpState-> registerBase-> INTEN & = (uint32_t) (~ (0x01u << endpointIndex));
            while (((lpc3511IpState-> registerBase-> INTEN & (0x01u << endpointIndex)) >> endpointIndex)! = 0)
            {
            }
            lpc3511IpState-> registerBase-> EPSKIP | = (0x01U << endpointIndex);
            while (lpc3511IpState-> registerBase-> EPSKIP & (0x01U << endpointIndex))
            {
            }
        }
        #endif
        
When requesting to send or receive I authorize

    if ((endpointIndex >> 1U)! = USB_CONTROL_ENDPOINT)
    {
        lpc3511IpState-> registerBase-> INTEN | = (uint32_t) (0x01u << endpointIndex);
        while (((lpc3511IpState-> registerBase-> INTEN & (0x01u << endpointIndex)) >> endpointIndex) == 0)
        {
        }
    }
    
But it's possible to skip the interrupt and it's necessary to watch INTSTAT without the INTEN mask in the function USB_DeviceLpcIp3511IsrFunction
    interruptStatus = lpc3511IpState-> registerBase-> INTSTAT;
    lpc3511IpState-> registerBase-> INTSTAT = interruptStatus;
    // interruptStatus & = lpc3511IpState-> registerBase-> INTEN;
    
Such a crutch

0 Kudos
945 Views
dark0711
Contributor III

My code

0 Kudos