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();
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