Hi guys, long time no talk! Ok, here’s what’s going on:
I have written code to communicate via UART with a bno055 inertial measurement unit board. The board requires UART communication at 115200 baud. No problem.
In my code, I send a command packet of five bytes and then wait for a two byte response. I have a blocking “while” loop in my code that waits until I’ve received the two byte response before progressing. The problem is I’m hanging in that blocking while loop because the two bytes aren’t coming in. However, I have a saleae logic analyzer on the RX line so I know that I am indeed getting two bytes, 0xEE and 0x01. Furthermore, I get into my RX interrupt once, but only once. When my code doesn’t get a two byte response it resends the command, which causes two more bytes to come back on the RX line from the bno055. With my logical analyzer I can see a ton of bytes coming in over the RX line when I let the code run, but I’m only getting into my RX interrupt once in the very beginning of my code. I’ve done a lot of troubleshooting and it seems like my lack of getting back into the RX interrupt must be the reason my code is not functioning. Everything else - shifting the commands out via the EOT TX interrupt, for instance - seems to be working just fine, corroborated by my logic analyzer. But my code hangs waiting for a two byte data packet that won't show up.
My question is: why am I only getting into my RX interrupt once? I have disabled the FIFO for UART 2, so I should be getting into my RX interrupt every time I receive a byte. I can’t figure out where I must have gone wrong. I have attached the code for my UART 2 initialization and ISR. If anyone has any ideas, please let me know.
Thanks!
void uart2_init(){ //initializes UART2 //sets up transmit and receive interrupts //0. Init Clock to UART2 and Port D SysCtlPeripheralEnable(SYSCTL_PERIPH_UART2); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD); //Give it time for clocks to start SysCtlDelay(10); //Disable UART before programming UARTDisable(UART2_BASE); //1. set baud rate, txe/rxe, stp2 (clear then and fen), and wlen (8 bit_) UARTConfigSetExpClk(UART2_BASE, SysCtlClockGet(), 115200, (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE)); UARTFIFODisable(UART2_BASE); //DISABLE FIFO. This should make my interrupt every time I get a byte. //1.5. Set up AFSEL To D6, D7 and UNLOCK D7 HWREG(GPIO_PORTD_BASE+GPIO_O_LOCK) = GPIO_LOCK_KEY; HWREG(GPIO_PORTD_BASE+GPIO_O_CR) |= GPIO_PIN_7; SysCtlDelay(30); GPIOPinConfigure(GPIO_PD6_U2RX); GPIOPinConfigure(GPIO_PD7_U2TX); //Set D6 as Input (RX) and D7 as Output (TX) GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_7); GPIOPinTypeGPIOInput(GPIO_PORTD_BASE, GPIO_PIN_6); //A little redundancy shouldn't hurt. GPIOPinTypeUART(GPIO_PORTD_BASE, GPIO_PIN_6 | GPIO_PIN_7); //Enable Global NVIC Interrupt IntEnable(INT_UART2); //Enable Local Interrupts UARTIntEnable(UART2_BASE, (UART_INT_TX | UART_INT_RX)); //enable Tx and Rx int UARTTxIntModeSet(UART2_BASE, UART_TXINT_MODE_EOT); //set Tx mode to EOT UARTFIFOLevelSet(UART2_BASE, UART_FIFO_TX1_8, UART_FIFO_RX1_8); //set Rx to trigger with two bytes //Disable for now so I don't get stuck in the TX isr. UARTIntDisable(UART2_BASE, UART_INT_TX); //Link a function to the UART Interrupt UARTIntRegister(UART2_BASE, isr_uart2); //Enable UART2 UARTEnable(UART2_BASE); //these will change based on our state, but we can use this as a table of contents array_tx[index_start_byte] = start_byte; array_tx[index_rw] = write; array_tx[index_reg_address] = reg_address_page; array_tx[index_data_length] = 0x01; array_tx[index_data] = page_zero; // printf("INIT: UART2\n"); } //printf(" \n"); void isr_uart2(void){ uint32_t trigger; trigger = UARTIntStatus(UART2_BASE, true); if ((trigger & UART_INT_RX)== UART_INT_RX){ //ISR triggers each time I receive a byte. printf("RX: UART2 ISR.\n"); printf("RX: Index: %u \n", index_rx); UARTIntClear(UART2_BASE, UART_INT_RX); array_rx[index_rx] = UARTCharGet(UART2_BASE); printf("Data Received: %u \n", array_rx[index_rx]); index_rx++; if (array_rx[0] == 0xEE && index_rx > 1){ printf("In RX If \n"); index_rx = 0; // if (array_rx[1] != 0x01){datapacketsuccess = false;} // else if (array_rx[1] == 0x01){datapacketsuccess = true;} switch (array_rx[1]){ case 0x01: printf("WRITE_SUCCESS \n"); datapacketsuccess = true; break; case 0x03: printf("WRITE_FAIL \n"); break; case 0x04: printf("REGMAP_INVALID_ADDRESS \n"); break; case 0x06: printf("WRONG_START_BYTE \n"); break; case 0x07: printf("BUS_OVER_RUN_ERROR \n"); break; case 0x08: printf("MAX_LENGTH_ERROR \n"); break; case 0x09: printf("MIN_LENGTH_ERROR \n"); break; case 0x0A: printf("RECEIVE_CHARACTER_TIMEOUT \n"); break; default: printf("There was an error. \n"); break; } datapacketreceived = true; } if (array_rx[0] == 0xBB && index_rx>7){ printf("RX: 0xBB // Data Packet Received \n"); index_rx=0; } } if ((trigger & UART_INT_TX) == UART_INT_TX){ //printf("TX: In UART2 Transmit ISR\n"); UARTIntClear(UART2_BASE, UART_INT_TX); UARTCharPut(UART2_BASE, array_tx[index]); //printf("%u \n", index); index++; if (index>packet_length_write){ UARTIntDisable(UART2_BASE, UART_INT_TX); index=1; //delay until I receive the data back from the bno055. while (datapacketreceived == false){printf("stuck waiting for data packet \n");} delay_ms(50); //If failed, resend the last packet if (datapacketsuccess == false){ printf("Data Packet Failed. Resending. \n"); UARTCharPut(UART2_BASE, start_byte); UARTIntEnable(UART2_BASE, UART_INT_TX); } else if (datapacketsuccess == true){ printf("Data Packet Success. State:: %u \n", state); //if successful, figure out what to do: switch (state){ case 1: //Page 0 successfully selected. Next is Config Mode Select. printf("TX: Page Select Done. Setting Boolean True. \n"); array_tx[index_reg_address] = reg_address_opr; pageselectdone = true; state = 2; break; case 2: //Config Mode successfully selected. Next is Power Mode Normal. printf("TX: Config Mode Select Done. \n"); array_tx[index_reg_address] = reg_address_power; configmodeselectdone = true; state = 3; break; case 3: //Power Mode Normal select done. Next is Selecting NDOF Mode. printf("TX: Power Mode Select Done. Setting Boolean True. \n"); array_tx[index_reg_address] = reg_address_opr; array_tx[index_data] = ndof_mode; powermodeselectdone = true; state = 4; break; case 4: printf("TX: NDOF Mode Select Done. Setting Commands to Read. \n"); array_tx[index_reg_address] = 0x3D;//reg_address_lia; array_tx[index_rw] = read; array_tx[index_data_length] = 0x06; oprmodeselectdone = true; state = 5; break; //Start regular 200 ms timer. Within the timer interrupt I will query the LIA. case 5: break; default: printf("TX: There was an Error in the State Number. \n"); break; } } } } }