This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

USB and UART interrupts together, problem!

Hi,

I am trying to setup a system where I use interrupts for the USB communication and UART but I have a problem, I can't use both at the same time ... Both work properly separated, once I try to use both it doesn't work anymore. I think it has to deal with the interrupt priority, because I still have the USB interrupt working once it has a higher priority (0) then the UART (2).
Someone has an idea? Thanks.
This is the initialization of both of them:

UART:

...
SCU_APBPeriphClockConfig(__UART0, ENABLE);
SCU_APBPeriphReset(__UART0,DISABLE);

SetCNTR(0);
SetISTR(0);
SCU_AHBPeriphClockConfig(__USB48M,ENABLE);

// UART Module //
UART_InitStructure.UART_WordLength = UART_WordLength_8D;
UART_InitStructure.UART_StopBits = UART_StopBits_1;
UART_InitStructure.UART_Parity = UART_Parity_No ;
UART_InitStructure.UART_BaudRate = 115200;
UART_InitStructure.UART_HardwareFlowControl = UART_HardwareFlowControl_None;
UART_InitStructure.UART_Mode = UART_Mode_Tx_Rx;
UART_InitStructure.UART_FIFO = UART_FIFO_Disable;

UART_DeInit(UART0);
UART_Init(UART0, &UART_InitStructure);

UART_ITConfig(UART0, UART_IT_Receive, ENABLE);
VIC_Config(UART0_ITLine, VIC_IRQ, 2);
VIC_ITCmd(UART0_ITLine, ENABLE);
/* Enable the UART0: start sending the transmit FIFO content to the hyperterminal */
UART_Cmd(UART0, ENABLE);
UART_ITConfig(UART0, UART_IT_Receive, ENABLE);
UART_LoopBackConfig(UART0, DISABLE);


USB:

SCU_USBCLKConfig(SCU_USBCLK_EXT);
// Enable USB clock //
SCU_AHBPeriphClockConfig(__USB, ENABLE);
SCU_AHBPeriphReset(__USB, DISABLE);
// USB Initialization
/* Enable and configure the priority of the USB_LP IRQ Channel*/
VIC_DeInit();
VIC_Config(USBLP_ITLine, VIC_IRQ, 0);
VIC_ITCmd(USBLP_ITLine, ENABLE);

/* USB initialization */
wInterrupt_Mask = IMR_MSK;

SetCNTR(0x0003);
Token_Event = 0; /* Flags of each endpoint interrupt */
pInformation = &Device_Info;
pInformation->ControlState = 2;
pProperty = &Device_Property;
/* Initialize devices one by one */
pProperty->Init();

  • Which MCU?
    There are minor differences in the VIC and USB implementation among MCU families.

    "I think it has to deal with the interrupt priority, because I still have the USB interrupt working once it has a higher priority (0) then the UART (2)."

    Usually, nested (priority) interrupt is not required for USB and UART interrupt support. Of course, it depends on your code. If you wait for a USB event in the UART ISR, you'll need nested interrupt. But in this case also, you can rewrite your code without nested interrupt.

    Tsuneo

  • I am using the STR912FA44 uC.

    I don't wait for a USB event in the UART ISR, so I suppost I don't need nested interrupts ...

    I don't get it why I can only make it working with one interrupt at the time ...

    This is the code of my interrupts:

    uart:

    void UART0_IRQHandler(void)
    {
     /*clear receive interrupt flag*/
      UART_ClearITPendingBit(UART0, UART_IT_Receive);
      UART_ClearITPendingBit(UART0,  UART_IT_Transmit);
      /*send back the received character*/
      while(UART_GetFlagStatus(UART0, UART_FLAG_TxFIFOFull) != RESET);
      UART_SendData(UART0, UART_ReceiveData(UART0));
      VIC1->VAR=0xFF;
    
    }
    

    USB

    void USB_Istr(void)
    {
            wIstr = _GetISTR();
            #if (IMR_MSK & ISTR_RESET)
            if (wIstr & ISTR_RESET & wInterrupt_Mask)
            {
                    _SetISTR((WORD)CLR_RESET);
                    Device_Property.Reset();
                    #ifdef RESET_Callback
                    RESET_Callback();
                    #endif
            }
            #endif
    
            #if     (IMR_MSK & ISTR_DOVR)
            if (wIstr & ISTR_DOVR & wInterrupt_Mask)
            {
                    _SetISTR((WORD)CLR_DOVR);
                    #ifdef DOVR_Callback
                    DOVR_Callback();
                    #endif
            }
            #endif
    
            #if     (IMR_MSK & ISTR_ERR)
            if (wIstr & ISTR_ERR & wInterrupt_Mask)
            {
                    _SetISTR((WORD)CLR_ERR);
                    #ifdef ERR_Callback
                    ERR_Callback();
                    #endif
            }
            #endif
    
            #if     (IMR_MSK & ISTR_WKUP)
            if (wIstr & ISTR_WKUP & wInterrupt_Mask)
            {
                    _SetISTR((WORD)CLR_WKUP);
                    Resume(RESUME_EXTERNAL);
                    #ifdef WKUP_Callback
                    WKUP_Callback();
                    #endif
            }
            #endif
    
            #if     (IMR_MSK & ISTR_SUSP)
            if (wIstr & ISTR_SUSP & wInterrupt_Mask)
            {
                    /* check if SUSPEND is possible */
                    if(fSuspendEnabled)
                    {
                            Suspend();
                    }
                    else
                    {
                            /* if not possible then resume after xx ms */
                            Resume(RESUME_LATER);
                    }
                    /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */
                    _SetISTR((WORD)CLR_SUSP);
                    #ifdef SUSP_Callback
                    SUSP_Callback();
                    #endif
            }
            #endif
    
            #if (IMR_MSK & ISTR_SOF)
            if (wIstr & ISTR_SOF & wInterrupt_Mask)
            {
                    _SetISTR((WORD)CLR_SOF);
                    #ifdef SOF_Callback
                    SOF_Callback();
                    #endif
            }
            #endif
    
            #if (IMR_MSK & ISTR_ESOF)
            if (wIstr & ISTR_ESOF & wInterrupt_Mask)
            {
                    _SetISTR((WORD)CLR_ESOF);
                    /* resume handling timing is made with ESOFs */
                    Resume(RESUME_ESOF); /* request without change of the machine state */
                    #ifdef ESOF_Callback
                    ESOF_Callback();
                    #endif
            }
            #endif
    
            #if     (IMR_MSK & ISTR_CTR)
            if (wIstr & ISTR_CTR & wInterrupt_Mask)
            {
                    /* servicing of the endpoint correct transfer interrupt */
                    /* clear of the CTR flag into the sub */
                    CTR_ISR();
                    #ifdef CTR_Callback
                    CTR_Callback();
                    #endif
            }
            #endif
    }/* USB_Istr */
    
    

  • Did you examine this example from ST Micro?

    "UM0290: STR7/STR9 USB developer kit"
    www.st.com/.../12721.pdf
    www.st.com/.../um0290.zip

    In the "str91x demos\Virtual Com Port" example,
    - UART interrupt is set up in Set_System() (hw_config.c)
    - USB interrupt is setup in USB_Interrupts_Config() (hw_config.c)
    - main() (main.c) calls these routines in this order Set_System(); USB_Interrupts_Config();

    Tsuneo

  • Hi Tsuneo,

    I run the usb demo that you give us the link below on my KEIL MCBSTR9 board with uVision3
    www.st.com/.../um0290.zip

    I find some interesting things I don't understand.

    1. If I use the following IRQ program, I will get an error "USB Device Not Recognized" on PC side.
    My IRQ prorgam is as follows:

    VectorAddr      EQU    0xFFFFF030       ; VIC Vector Address Register
    VectorAddrDaisy EQU    0xFC000030       ; Daisy VIC Vector Address Register
    
    
            AREA IRQ, CODE, READONLY
            ARM
    
            PRESERVE8
            ALIGN
            EXPORT  IRQHandler
    IRQHandler
            SUB     LR, LR, #4              ; Update Link Register
            STMFD   SP!, {R0-R12, LR}       ; Save Workspace & LR to Stack
            LDR     R0, =VectorAddr
            LDR     R0, [R0]                ; Read the Routine Address
            LDR     LR, =IRQReturnAddress   ; Read the Return Address
            BX      R0                      ; Branch to the IRQ Handler
    IRQReturnAddress
    
            LDMFD   SP!, {R0-R12, PC}^      ; Return to program
    
    
            END
    

    2. If I use the nested interrupt IRQ program below, the error "USB Device is not recognized" will disapear. Test the prorgam on the Hyperterminals on two PCs. The USB prorgam works properly. However, if I send the message continueouly on LABVIEW using USB virtual com port on one PC, I will receive truncated message on the hyperterminal of another PC using com port 1.

    VectorAddr      EQU    0xFFFFF030       ; VIC Vector Address Register
    VectorAddrDaisy EQU    0xFC000030       ; Daisy VIC Vector Address Register
    
    
            AREA IRQ, CODE, READONLY
            ARM
    
            PRESERVE8
            ALIGN
            EXPORT  IRQHandler
    
    IRQHandler
            SUB     LR, LR, #4              ; Update Link Register
            STMFD   SP!, {R0-R12, LR}       ; Save Workspace & LR to Stack
            MRS     R0, SPSR                ; Copy SPSR to R0
            STMFD   SP!, {R0, R1}           ; Save SPSR to Stack (8-byte)
            LDR     R0, =VectorAddr
            LDR     R0, [R0]                ; Read the Routine Address
            LDR     R1, =VectorAddrDaisy
            LDR     R1, [R1]
            ; Padding between the acknowledge and re-enable of interrupts
            ; For more details, please refer to the following URL
            ; www.arm.com/.../3682.html
            NOP
            NOP
            MSR     CPSR_c, #0x1F           ; Switch to SYS Mode and enable IRQ
            STMFD   SP!, {R0, LR}           ; Save Link Register (8-byte Stack)
            LDR     LR, =IRQReturnAddress   ; Read the Return Address
            BX      R0                      ; Branch to the IRQ Handler
    IRQReturnAddress
            LDMFD   SP!, {R0, LR}           ; Restore Link Register (8-byte Stack)
            MSR     CPSR_c, #0xD2           ; Switch to IRQ Mode
            LDR     R0, =VectorAddr         ; Write to the VectorAddress to clear
            STR     R0, [R0]                ; the respective Interrupt
            LDR     R1, =VectorAddrDaisy    ; Write to the VectorAddressDaisy to
            STR     R1, [R1]                ; clear the respective Interrupt
            LDMFD   SP!, {R0, R1}           ; Restore SPSR to R0
            MSR     SPSR_cxsf, R0           ; Restore SPSR
            LDMFD   SP!, {R0-R12, PC}^      ; Return to program
    
    
            END
    

    My questions are
    1. when PC will show "USB Device not Recognized"?
    2. why I will get truncated message?

    Thank you very much for your help.

    Lillian