STM32F10X timer - arm

I have a problem regarding the timer-interrupt with my stm32f10 controller.
When I enable the counter of the timer the status register is set to
0x1F because the following flags are set: UIF, CC1IF, CC2IF, CC3IF, CC4IF
Here is what i did:
#include <Compiler.h>
#include <Debug.h>
#include <STM32F10xxx.h>
#include <Reset.h>
#include "Example.h"
#include <HW_TIM.h>
#include <HW_NVIC.h>
#include <HW_RCC.h>
#include <RegBit.h>
unsigned volatile int sr =0;
static void SetBASEPRI(WORD const basepriVal) {
register WORD basepriReg __asm("basepri");
basepriReg = basepriVal;
}
static void SetCONTROL(WORD const controlVal) {
register WORD controlReg __asm("control");
controlReg = controlVal;
}
static void MainInit(void) {
STM32F10xxx_Config();
SetBASEPRI(0U);
PeripheryEnable(RCC_TIM2);
SET_RBINDEX_REG_BIT(TIM, 2, DIER, UIE);
SET_RBINDEX_REG_BIT(TIM, 2, DIER, CC1IE);
SET_RBINDEX_REG_BIT(TIM, 2, DIER, CC2IE);
SET_RBINDEX_REG_BIT(TIM, 2, DIER, CC3IE);
SET_RBINDEX_REG_BIT(TIM, 2, DIER, CC4IE);
InterruptEnable(NVIC_TIM2);
SetCONTROL(1U);
}
void timInit(void){
TIM2.PSC = 0x0024;
TIM2.ARR = 0xFFFF;
TIM2.CCR[0] = 0x00FF;
TIM2.CCR[1] = 0x0A00;
TIM2.CCR[2] = 0x0F00;
TIM2.CCR[3] = 0xF000;
SET_RBINDEX_REG_BIT(TIM, 2, CR1, CEN);
}
__declspec(noreturn) int main() {
MainInit();
timInit();
while(1);
}
void IRQ_TIM2(void){
//Delet IFs in SR
//trying to clear SR by reading the register
sr = TIM2.SR;
sr= GET_RBINDEX_REG_BIT(TIM,2,SR,UIF);
//trying to clear SR by resetting the single bits
RES_RBINDEX_REG_BIT(TIM, 2, SR, CC1IF);
RES_RBINDEX_REG_BIT(TIM, 2, SR, CC2IF);
RES_RBINDEX_REG_BIT(TIM, 2, SR, CC3IF);
RES_RBINDEX_REG_BIT(TIM, 2, SR, CC4IF);
RES_RBINDEX_REG_BIT(TIM, 2, SR, UIF);
//trying to clear SR bei assigning 0 to SR
TIM2.SR=0;
}
void IRQ_SysTick(void){
}
void IRQ_HrdFault(void) { for ( ;; ) DEBUG_BREAK(1); }
void IRQ_UsgFault(void) { for ( ;; ) DEBUG_BREAK(1); }
void IRQ_BusFault(void) { for ( ;; ) DEBUG_BREAK(1); }
void IRQ_MemFault(void) { for ( ;; ) DEBUG_BREAK(1); }
void IRQ_NMI(void) { for ( ;; ) DEBUG_BREAK(1); }
As I said, the problem is that all the flags are set when the Counter-Enable-Bit(CEN) is set. And I can't delete them in the subroutine.

It's a bit late answer, but I faced today a similar problem I think this could help other people. First I doubt that the problem was that flags UIF, CC1IF, CC2IF, CC3IF, CC4IF are set or not set. If you check the Reference Manual on page 403 is written that those flags are set by the hardware, so when you reset them the hardware (which is running even when you are debugging) will set them automatically and you won't even notice the result. If you want to see the flags cleared with debugger I recommend to disable the timer and then perform some operations. Also it is a recommended style to check the source of the interrupt in the IRQ:
//comment the next line before release
#define DEBUG
void IRQ_TIM2(void){
//disable the timer for debug purpose
#ifdef DEBUG
TIM2->CR1 &= ~TIM_CR1_CEN;
#endif
//trying to clear SR by reading the register
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) {
TIM_ClearITPendingBit(TIM2, TIM_IT_Update); //clearing UIF
}
if(TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET) {
TIM_ClearITPendingBit(TIM2, TIM_IT_Update); //clearing CCIF
}
//etc...
//enable the timer
#ifdef DEBUG
TIM2->CR1 |= TIM_CR1_CEN;
#endif
}

Related

Is there a way to calculate -time interval- using Esp32 timers?

I want to calculate time interval with timers. I'm using arduino ide. Also i can not decide which library to useful.
I just tried something following code.
I'm using this library
#include <ESP32Time.h>
int a;
int b;
int ldrValue;
#define LDR 0
/* create a hardware timer */
hw_timer_t * timer = NULL;
int timeThatPast;
/* motor pin */
int motor = 14;
/* motor state */
volatile byte state = LOW;
void IRAM_ATTR onTimer(){
state = !state;
digitalWrite(motor, state);
}
void setup() {
Serial.begin(115200);
pinMode(motor, OUTPUT);
/* Use 1st timer of 4 */
/* 1 tick take 1/(80MHZ/80) = 1us so we set divider 80 and count up */
timer = timerBegin(0, 80, false);
/* Attach onTimer function to our timer */
timerAttachInterrupt(timer, &onTimer, true);
//********************ALARM*******************
/* Set alarm to call onTimer function every second 1 tick is 1us
=> 1 second is 1000000us */
/* Repeat the alarm (third parameter) */
timerAlarmWrite(timer, 7000000, false);
//********************************************
/* Start an alarm */
timerAlarmEnable(timer);
Serial.println("start timer");
}
void loop() {
int ldrValue = analogRead(LDR);
ldrValue = map(ldrValue, 0, 4095, 0, 10000);
if(ldrValue > 8500){
a = timerRead(timer);
digitalWrite(motor,HIGH);
while(1){
int ldrValue = analogRead(LDR);
ldrValue = map(ldrValue, 0, 4095, 0, 10000);
if(ldrValue < 8500){
b = timerRead(timer);
digitalWrite(motor,LOW);
Serial.print("Entering Loop");
Serial.println(a);
Serial.println("**********");
Serial.println("**********");
Serial.print("Exiting loop");
Serial.println(b);
int difference = b - a;
Serial.println("Difference");
Serial.println(difference);
break;
}
}
}
}
Use millis or micros if you need more precise timing.
Here is an example sketch:
long lastDoTime = 0;
void setup(){
Serial.begin(115200);
delay(1000);
Serial.println("Hello! We will do something at every ms");
}
void doThisAtEvery(int ms){
if( millis() - lastDoTime >= ms ){
// Must save the lastDoTime
lastDoTime = millis();
// Do some stuff at every ms
}
}
void loop(){
// It will do the thing in every 100 ms.
doThisAtEvery(100);
}
If you want to toggle a pin let's say every 100 microsec
long lastToggleTime = 0;
int motorPin = 14;
boolean lastPinState = LOW;
void setup(){
Serial.begin(115200);
}
void togglePinEvery(int micros){
if( micros() - lastToggleTime >= micros ){
lastToggleTime = micros();
digitalWrite(motorPin,!lastPinState);
lastPinState = !lastPinState;
}
}
void loop(){
togglePinEvery(100);
}
EDIT Since you wanted timers only.
Here is a detailed explanation about timers: https://techtutorialsx.com/2017/10/07/esp32-arduino-timer-interrupts/
Code example:
volatile int interruptCounter;
int totalInterruptCounter;
hw_timer_t * timer = NULL;
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
void IRAM_ATTR onTimer() {
portENTER_CRITICAL_ISR(&timerMux);
interruptCounter++;
portEXIT_CRITICAL_ISR(&timerMux);
}
void setup() {
Serial.begin(115200);
timer = timerBegin(0, 80, true);
timerAttachInterrupt(timer, &onTimer, true);
timerAlarmWrite(timer, 1000000, true);
timerAlarmEnable(timer);
}
void loop() {
if (interruptCounter > 0) {
portENTER_CRITICAL(&timerMux);
interruptCounter--;
portEXIT_CRITICAL(&timerMux);
totalInterruptCounter++;
Serial.print("An interrupt as occurred. Total number: ");
Serial.println(totalInterruptCounter);
}
}

Is this the right way to access function?

I am currently using "STM32F429I-DISC1" with joystick. I am trying to draw something on the LCD screen and using joystick move this object. My drawing is working fine, but I have the error: " void value not ignored as it ought to be".
This two lines have problems...
localX = Joy_ReadXY(CTRL_REG_IN3);
localY = Joy_ReadXY(CTRL_REG_IN4);
Can someone please tell me, how I can fix this error?
And why I see this error?
Main.c
#include "stm32f429i_discovery_lcd.h"
#define CTRL_REG_IN3 0b00011000
#define CTRL_REG_IN4 0b00100000
SemaphoreHandle_t xMutex;
Joystick_data xy;
void vTaskFunction1(void *pvParameters) {
uint16_t localX;
uint16_t localY;
for(;;) {
localX = Joy_ReadXY(CTRL_REG_IN3);
localY = Joy_ReadXY(CTRL_REG_IN4);
xSemaphoreTake( xMutex, portMAX_DELAY );
xy.x = localX;
xy.y = localY;
xSemaphoreGive( xMutex );
HAL_Delay(10);
}
}
void vTaskFunction2(void *pvParameters) {
uint32_t xCoord = 240/2;
uint32_t yCoord = 320/2;
uint8_t reads = 0;
uint8_t ballRadius = 5;
uint16_t xLimitMin = ballRadius+25;
uint16_t xLimitMax = 240-ballRadius-25;
uint16_t yLimitMin = ballRadius+25;
uint16_t yLimitMax = 320-ballRadius-25;
for(;;) {
xSemaphoreTake( xMutex, portMAX_DELAY );
if (xy.x > 3000 && !(xCoord < xLimitMin))
xCoord -= 5;
if (xy.x < 1000 && !(xCoord > xLimitMax))
xCoord += 5;
if (xy.y > 3000 && !(yCoord < yLimitMin))
yCoord -= 5;
if (xy.y < 1000 && !(yCoord > yLimitMax))
yCoord += 5;
reads++;
BSP_LCD_Clear(LCD_COLOR_WHITE);
BSP_LCD_DrawCircle(xCoord, yCoord, ballRadius);
BSP_LCD_FillCircle(xCoord, yCoord, ballRadius);
xSemaphoreGive(xMutex);
HAL_Delay(20);
}
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_SPI4_Init();
MX_TIM1_Init();
MX_USART1_UART_Init();
// LCD Things
BSP_LCD_Init();
BSP_LCD_LayerDefaultInit(1, LCD_FRAME_BUFFER);
BSP_LCD_SelectLayer(1);
BSP_LCD_SetBackColor(LCD_COLOR_WHITE); // Vali meelepärane värv
BSP_LCD_Clear(LCD_COLOR_WHITE);
BSP_LCD_SetTextColor(LCD_COLOR_DARKBLUE); // Vali meelepärane värv
MX_FREERTOS_Init();
if ( xMutex == NULL )
{
xMutex = xSemaphoreCreateMutex();
if ( ( xMutex ) != NULL )
xSemaphoreGive( ( xMutex ) );
}
xTaskCreate(vTaskFunction1, "Task 1", 100, NULL, 1, NULL);
xTaskCreate(vTaskFunction2, "Task 2", 100, NULL, 1, NULL);
vTaskStartScheduler();
osKernelStart();
while (1)
{
}
}
Read joystick function (joystick.c)
#include <stdio.h>
#include <main.h>
#include "gpio.h"
#include "spi.h"
#define READ_SLAVE_OPERATION 0b10000000
#define READ_INCR_SLAVE_OPERATION 0b11000000
#define WRITE_SLAVE_OPERATION 0b00000000
#define CTRL_REG_IN3 0b00000011
#define CTRL_REG_IN4 0b00000100
#define OUT_X_L 0x28
#define OUT_X_H 0x29
#define OUT_Y_L 0x2A
#define OUT_Y_H 0x2B
#define OUT_Z_L 0x2C
#define OUT_Z_H 0x2D
#define JOY_CS_LOW() HAL_GPIO_WritePin(JOY_CS_GPIO_PORT, JOY_CS_PIN, 0)
#define JOY_CS_HIGH() HAL_GPIO_WritePin(JOY_CS_GPIO_PORT, JOY_CS_PIN, 1)
#define JOY_CS_GPIO_PORT GPIOC
#define JOY_CS_PIN GPIO_PIN_13
int16_t Joy_ReadXY(uint8_t reg1){
uint8_t pTxData1[2] = {reg1, 0};
uint8_t pRxData1[2] = {0, 0};
JOY_CS_LOW();
HAL_SPI_TransmitReceive(&hspi4, pTxData1, pRxData1, 2, HAL_MAX_DELAY);
JOY_CS_HIGH();
return pRxData1[0] << 8 | pRxData1[1];
}
Here, in Main.c, you call the function before telling the compiler about what parameters and what return value types it has.
localX = Joy_ReadXY(CTRL_REG_IN3);
localY = Joy_ReadXY(CTRL_REG_IN4)
That confused the compiler and it starts "guessing" about them.
Guessing that it is a void-returning function, the compiler then complains that you are expecting a return value from a function which does return void i.e. nothing.
The returned void should be ignored, instead of attempting to write it to a variable. At least that is what the compiler thinks...
To fix it, you should explain to the compiler that there is a function elsewhere, with name, parameters and return value type. That is done by providing the prototype
int16_t Joy_ReadXY(uint8_t reg1);
It needs to be done before the function body in which the the extern function is first called. (And you already confirmed in comments that it fixes the described problem in your code.)
Note that for the other shown functions this is not needed, because they are defined (with head and body) before they are called.
Similar for other functions, which have their prototype provided in the header you include early on.
Actually, putting the prototype of your function into a header and including that similarily would be the best way to solve this.

How to make a single function from repetitive code?

I'm writing some code for my embedded system. As I'm adding more different channels of the same periphery, I'm getting code that's really repetitive. For example:
void pos1_write_read(int *pwriteData)
{
// Reset rx buffer and transfer done flag
memset(m_rx_buf0, 0, m_length0);
spi0_xfer_done = false;
nrfx_spi_xfer_desc_t m_pos1_write;
m_pos1_write.p_tx_buffer = pwriteData;
m_pos1_write.tx_length = m_length0;
m_pos1_write.p_rx_buffer = m_rx_buf0;
m_pos1_write.rx_length = m_length0;
nrf_gpio_pin_clear(SPI0_CS0_PIN); //Set CS0 to 0 (on)
APP_ERROR_CHECK(nrfx_spi_xfer(&spi0, &spi0_transfer, NULL));
while (!spi0_xfer_done){} //Wait until the tranfser is done
nrf_gpio_pin_set(SPI0_CS0_PIN); //Set CS0 to 1 (off)
}
void pos2_write_read(int *pwriteData)
{
// Reset rx buffer and transfer done flag
memset(m_rx_buf0, 0, m_length0);
spi0_xfer_done = false;
nrfx_spi_xfer_desc_t m_pos2_write;
m_pos2_write.p_tx_buffer = pwriteData;
m_pos2_write.tx_length = m_length0;
m_pos2_write.p_rx_buffer = m_rx_buf0;
m_pos2_write.rx_length = m_length0;
nrf_gpio_pin_clear(SPI0_CS1_PIN); //Set CS1 to 0 (on)
APP_ERROR_CHECK(nrfx_spi_xfer(&spi0, &spi0_transfer, NULL));
while (!spi0_xfer_done){} //Wait until the tranfser is done
nrf_gpio_pin_set(SPI0_CS1_PIN); //Set CS1 to 1 (off)
}
How would I write a single function that could be used in both examples? Is there any general good practice to avoid repeating the same code?
Finding the right design depends on how it's intended to be used, how generic you feel is appropriate, etc. There is no single correct way to do this. But the naive solution based only on your code snippet is something like:
void write_read(int *pwriteData, int pin)
{
// Reset rx buffer and transfer done flag
memset(m_rx_buf0, 0, m_length0);
spi0_xfer_done = false;
nrfx_spi_xfer_desc_t m_pos1_write;
m_pos1_write.p_tx_buffer = pwriteData;
m_pos1_write.tx_length = m_length0;
m_pos1_write.p_rx_buffer = m_rx_buf0;
m_pos1_write.rx_length = m_length0;
nrf_gpio_pin_clear(pin); //Set CS0 to 0 (on)
APP_ERROR_CHECK(nrfx_spi_xfer(&spi0, &spi0_transfer, NULL));
while (!spi0_xfer_done){} //Wait until the tranfser is done
nrf_gpio_pin_set(pin); //Set CS0 to 1 (off)
}
void pos1_write_read(int *pwriteData)
{
write_read(pwriteData, SPI0_CS0_PIN);
}
void pos2_write_read(int *pwriteData)
{
write_read(pwriteData, SPI0_CS1_PIN);
}
The idea is to just take the common code, and parameterize anything that's different between them.
The only real difference is the SC pin, which you can pass as an argument:
void pos_write_read(int *pwriteData, uint32_t pin)
{
// Reset rx buffer and transfer done flag
memset(m_rx_buf0, 0, m_length0);
spi0_xfer_done = false;
nrfx_spi_xfer_desc_t m_pos_write;
m_pos_write.p_tx_buffer = pwriteData;
m_pos_write.tx_length = m_length0;
m_pos_write.p_rx_buffer = m_rx_buf0;
m_pos_write.rx_length = m_length0;
nrf_gpio_pin_clear(pin); //Set CS to 0 (on)
APP_ERROR_CHECK(nrfx_spi_xfer(&spi0, &spi0_transfer, NULL));
while (!spi0_xfer_done){} //Wait until the tranfser is done
nrf_gpio_pin_set(pin); //Set CS to 1 (off)
}
/* This allows you to do the following: */
void pos1_write_read(int *pwriteData)
{
pos_write_read(pwriteData, SPI0_CS0_PIN);
}
void pos2_write_read(int *pwriteData)
{
pos_write_read(pwriteData, SPI0_CS1_PIN);
}

GPIO interrupt for different pins in PSoC 1

I have faced a problem connected with GPIO interrupt.
The task is to make a simple UI interface, so I need to use 3 buttons.
The problem is that I don't understand how to use GPIO interrupt for different pins and all my buttons work the same way.
here is the code:
#include <m8c.h> // part specific constants and macros
#include "PSoCAPI.h" // PSoC API definitions for all User Modules
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int value; // the actual value which is used in the module
char string[16]; // string that is printed in LCD for user
} UI_ELEMENT;
#define FIRST_LEVEL 3
#define SECOND_LEVEL 3
#define PWM 0
#define PGA 1
#define ADC 2
#define PWM_STATE 0
#define PWM_PERIOD 1
#define PWM_WIDTH 2
#define PWM_STATE_OFF 0
#define PWM_STATE_ON 1
volatile int buttonRightPressed = 0;
#pragma interrupt_handler buttonRightInt
void buttonRightInt(void){
// disable button interrupt
M8C_DisableIntMask(INT_MSK0, INT_MSK0_GPIO);
buttonRightPressed = 1;
}
void initialize_LCD(void){
LCD_Position(0,0);
LCD_PrCString("PWM");
LCD_Position(1,0);
LCD_PrCString("< select >");
}
void update_LCD(int* lvl1){
if (*lvl1 == PWM || *lvl1 == 3){
LCD_Position(0,0);
LCD_PrCString("PWM");
*lvl1 = 0;
}
else if (*lvl1 == PGA){
LCD_Position(0,0);
LCD_PrCString("PGA");
}
else if (*lvl1 == ADC){
LCD_Position(0,0);
LCD_PrCString("ADC");
}
}
void main(void)
{
UI_ELEMENT userInterface[FIRST_LEVEL][SECOND_LEVEL];
int level_1_steper = PWM;
int i;
M8C_EnableGInt ; // Uncomment this line to enable Global Interrupts
PWM8_EnableInt();
LCD_Start();
M8C_EnableIntMask(INT_MSK0, INT_MSK0_GPIO);
initialize_LCD(); // set 'PWM' for upper row, '< select >' for lower row
while (1){
if (buttonRightPressed == 1){
for ( i = 0; i < 350; i++);
level_1_steper++;
update_LCD(&level_1_steper);
buttonRightPressed = 0;
// enable button interrupt again
M8C_EnableIntMask(INT_MSK0, INT_MSK0_GPIO);
}
}
}
Problem resolved! As usually solution is quite simple: use GPIO interrupt but test which button has been pressed. GPIO iterrupt:
void buttonInt(void){ // disable button interrupt
M8C_DisableIntMask(INT_MSK0, INT_MSK0_GPIO);
if (Right_Data_ADDR & Right_MASK) buttonRightPressed = 1;
if (Left_Data_ADDR & Left_MASK) buttonLeftPressed = 1;
if (Select_Data_ADDR & Select_MASK) buttonSelectPressed = 1;
}

Uart Check Receive Buffer interrupt vs. polling

Hello I am learning how to use the Uart by using interrupts in Nios and I am not sure how to start. I have made it in polling, but I am not sure how to start using interrupts.
Any help would be appreciated
Here is my code
#include <stdio.h> // for NULL
#include <sys/alt_irq.h> // for irq support function
#include "system.h" // for QSYS defines
#include "nios_std_types.h" // for standard embedded types
#define JTAG_DATA_REG_OFFSET 0
#define JTAG_CNTRL_REG_OFFSET 1
#define JTAG_UART_WSPACE_MASK 0xFFFF0000
#define JTAG_UART_RV_BIT_MASK 0x00008000
#define JTAG_UART_DATA_MASK 0x000000FF
volatile uint32* uartDataRegPtr = (uint32*)JTAG_UART_0_BASE;
volatile uint32* uartCntrlRegPtr = ((uint32*)JTAG_UART_0_BASE +
JTAG_CNTRL_REG_OFFSET);
void uart_SendByte (uint8 byte);
void uart_SendString (uint8 * msg);
//uint32 uart_checkRecvBuffer (uint8 *byte);
uint32 done = FALSE;
void uart_SendString (uint8 * msg)
{
int i = 0;
while(msg[i] != '\0')
{
uart_SendByte(msg[i]);
i++;
}
} /* uart_SendString */
void uart_SendByte (uint8 byte)
{
uint32 WSPACE_Temp = *uartCntrlRegPtr;
while((WSPACE_Temp & JTAG_UART_WSPACE_MASK) == 0 )
{
WSPACE_Temp = *uartCntrlRegPtr;
}
*uartDataRegPtr = byte;
} /* uart_SendByte */
uint32 uart_checkRecvBuffer (uint8 *byte)
{
uint32 return_value;
uint32 DataReg = *uartDataRegPtr;
*byte = (uint8)(DataReg & JTAG_UART_DATA_MASK);
return_value = DataReg & JTAG_UART_RV_BIT_MASK;
return_value = return_value >> 15;
return return_value;
} /* uart_checkRecvBuffer */
void uart_RecvBufferIsr (void* context)
{
} /* uart_RecvBufferIsr */
int main(void)
{
uint8* test_msg = (uint8*)"This is a test message.\n";
//alt_ic_isr_register ( ); // used for 2nd part when interrupts are enabled
uart_SendString (test_msg);
uart_SendString ((uint8*)"Enter a '.' to exist the program\n\n");
while (!done)
{
uint8 character_from_uart;
if (uart_checkRecvBuffer(&character_from_uart))
{
uart_SendByte(character_from_uart);
}
// do nothing
} /* while */
uart_SendString((uint8*)"\n\nDetected '.'.\n");
uart_SendString((uint8*)"Program existing....\n");
return 0;
} /* main */
I am suppose to use the uart_RecvBufferIsr instead of uart_checkRecvBuffer. How can tackle this situation?
You will need to register your interrupt handler by using alt_ic_isr_register(), which will then be called when an interrupt is raised. Details can be found (including some sample code) in this NIOS II PDF document from Altera.
As far as modifying your code to use the interrupt, here is what I would do:
Remove uart_checkRecvBuffer();
Change uart_RecvBufferIsr() to something like (sorry no compiler here so can't check syntax/functioning):
volatile uint32 recv_flag = 0;
volatile uint8 recv_char;
void uart_RecvBufferIsr(void *context)
{
uint32 DataReg = *uartDataRegPtr;
recv_char = (uint8)(DataReg & JTAG_UART_DATA_MASK);
recv_flag = (DataReg & JTAG_UART_RV_BIT_MASK) >> 15;
}
The moral of the story with the code above is that you should keep your interrupts as short as possible and let anything that is not strictly necessary to be done outside (perhaps by simplifying the logic I used with the recv_char and recv_flag).
And then change your loop to something like:
while (!done)
{
if (recv_flag)
{
uart_SendByte(recv_byte);
recv_flag = 0;
}
}
Note that there could be issues with what I've done depending on the speed of your port - if characters are received too quickly for the "while" loop above to process them, you would be losing some characters.
Finally, note that I declared some variables as "volatile" to prevent the compiler from keeping them in registers for example in the while loop.
But hopefully this will get you going.

Resources