Problem Scanf()

kamran99kamran wrote on Monday, March 17, 2014:

this does not work !!! if scanf is activate, then over the terminal does stop und doesn’t work!!!
//scanf("%i\n\r",&e);
//printf("%i",e);

And using with getchar the task is working very good!
I am using ARM COrtex M4F!

Maybe this is about problem with uart()!

Thanks!
reagrds Kamran

// =========================================================
// Copyright© 2014 Kamran
// Beschreibung: Abfrage + Ausgabe + DAC + ADC + Pin D8
// + FrreRTOS
// =========================================================

//Example code to loop back the data sent to USART2 on STM32F4DISCOVERY

//Inlcude header files
#include “stm32f4xx.h”
#include “FreeRTOS.h”
#include “task.h”
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include “stm32f4xx.h”
#include “stm32f4xx_conf.h”
#include “stm32f4xx_usart.h”
#include “stm32f4xx_rcc.h”
#include “stm32f4xx_gpio.h”
#include “system_stm32f4xx.h”
#include “FreeRTOSConfig.h”
#include “stm32f4xx_tim.h”
#include “uart.h”

//Task For Sending Data Via USART
static void UsartTask(void *pvParameters)
{
int x;
printf("\r\n"); // malloc
printf(">Hero\r\n"); // malloc 2
putchar(‘t’);
putchar(‘y’);
printf("\r\n"); // malloc 3

while(1) {

// this does not work !!! if scanf is activate, then over the //terminal stop und doesn’t work!!!
//scanf("%i\n\r",&e);
//printf("%i",e);

int c;
printf("\r\n");
c = getchar();
putchar(c);
printf("\r\n");

printf("das war c: %c \n\r", c);





}while(1);

}

//Initialize GPIO and USART6
void initx(void)
{
uart_init(9600);
}

//Main Function
int main(void)
{
char buffer[256];

//Call initx(); To Initialize USART & GPIO
initx();


//Create Task For USART
xTaskCreate(UsartTask, (signed char*)"UsartTask", 128, NULL, tskIDLE_PRIORITY+1, NULL);

//Call Scheduler
vTaskStartScheduler();

}

/***************************************************************/

#include “uart.h”
#include “stm32f4xx.h”
#include “ringbuf.h”
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>

#define RX_SIZE 128
#define TX_SIZE 128

struct ringbuf rx_buf = { .buf = (char[RX_SIZE]) {}, .bufsize = RX_SIZE };
struct ringbuf tx_buf = { .buf = (char[TX_SIZE]) {}, .bufsize = TX_SIZE };

static volatile struct uart_stats {
uint32_t rx_overrun;
uint32_t rx_bytes;
uint32_t tx_bytes;
} uart_stats;

void USART6_IRQHandler(void)
{
if (USART6->SR & USART_SR_RXNE) {
char c = USART6->DR;
if (!rb_putc(&rx_buf, c))
uart_stats.rx_overrun++;
else {
#if 0
/* ECHO */
rb_putc(&tx_buf, c);
USART6->CR1 |= USART_CR1_TXEIE;
#endif
uart_stats.rx_bytes++;
}
}

if (USART6->SR & USART_SR_TXE) {
    char c;
    if (rb_getc(&tx_buf, &c)) {
        // send a queued byte
        //
        USART6->DR = c;
    }
    else {
        // nothing to send, disable interrupt
        //
        USART6->CR1 &= ~USART_CR1_TXEIE;
    }
    uart_stats.tx_bytes++;
}

}

int uart_chars_avail(void)
{
return rx_buf.len;
}

ssize_t uart_write_r(struct _reent *r, int fd, const void *ptr, size_t len)
{
const char c = (const char) ptr;

for (int i = 0; i < len; i++) {
    while (!rb_putc(&tx_buf, *c));
    c++;

    // Enable TX empty interrupt
    USART6->CR1 |= USART_CR1_TXEIE; // CR1 -> SR
}
return len;

}

ssize_t uart_read_r(struct _reent *r, int fd, void *ptr, size_t len)
{
while (!rx_buf.len);

if (len > rx_buf.len)
    len = rx_buf.len;

char *c = (char*)ptr;
for (int i = 0; i < len; i++)
    rb_getc(&rx_buf, c++);

return len;

}

void uart_poll_send(const char *ch)
{
while (*ch) {
USART6->DR = *ch++ & 0xff;
while (!(USART6->SR & USART_FLAG_TXE));
uart_stats.tx_bytes++;
}
}

/**

  • Initialize UART.
  • \param baudrate Baudrate
  • PC6 USART6_TXD
  • PC7 USART7_RXD

*/
void uart_init(int baudrate)
{
// Enable peripheral clocks
//
RCC->AHB1ENR |= RCC_AHB1Periph_GPIOC;
RCC->APB2ENR |= RCC_APB2Periph_USART6;

#if 0
// Initialize Serial Port
//
GPIO_Init(GPIOC, &(GPIO_InitTypeDef) {
    .GPIO_Pin   = GPIO_Pin_6,
    .GPIO_Speed = GPIO_Speed_50MHz,
    .GPIO_Mode  = GPIO_Mode_AF,
    .GPIO_OType = GPIO_OType_PP
});

GPIO_Init(GPIOC, &(GPIO_InitTypeDef) {
    .GPIO_Pin = GPIO_Pin_7,
    .GPIO_Mode = GPIO_Mode_IN,
    .GPIO_PuPd = GPIO_PuPd_UP
});

#endif

#if 1
// Initialize Serial Port
//
GPIO_Init(GPIOC, &(GPIO_InitTypeDef) {
    .GPIO_Pin   = GPIO_Pin_6,
    .GPIO_Speed = GPIO_Speed_50MHz,
    .GPIO_Mode  = GPIO_Mode_AF,
    .GPIO_PuPd = GPIO_PuPd_NOPULL,
    .GPIO_OType = GPIO_OType_PP
});

GPIO_Init(GPIOC, &(GPIO_InitTypeDef) {
    .GPIO_Pin = GPIO_Pin_7,
    .GPIO_Speed = GPIO_Speed_50MHz,
    .GPIO_Mode = GPIO_Mode_AF,
    .GPIO_PuPd = GPIO_PuPd_NOPULL,
    .GPIO_OType = GPIO_OType_PP
});

#endif

GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_USART6);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_USART6);

USART_Init(USART6, &(USART_InitTypeDef) {
    .USART_BaudRate = baudrate,
    .USART_WordLength = USART_WordLength_8b,
    .USART_StopBits = USART_StopBits_1,
    .USART_Parity = USART_Parity_No ,
    .USART_HardwareFlowControl = USART_HardwareFlowControl_None,
    .USART_Mode = USART_Mode_Rx | USART_Mode_Tx
});

NVIC_Init(&(NVIC_InitTypeDef) {
    .NVIC_IRQChannel = USART6_IRQn,
    .NVIC_IRQChannelPreemptionPriority = configLIBRARY_KERNEL_INTERRUPT_PRIORITY,
    .NVIC_IRQChannelSubPriority = 0,
    .NVIC_IRQChannelCmd = ENABLE
});

 	USART_ITConfig(USART6, USART_IT_RXNE , ENABLE);
USART_Cmd(USART6, ENABLE);

}

davedoors wrote on Monday, March 17, 2014:

Is your question related to FreeRTOS? If it is even implemented, how are you expecting scanf() to work in whichever C library you are using? I would expect it to make everything stop while it waited from a line of input, which I think is what you said it did.

rtel wrote on Monday, March 17, 2014:

Is your scanf() configured to accept input from the UART? If so, how is this implemented? If it is polling the input then you could call scanf() from a single task provided that task was at a very low priority so as not to starve any higher priority tasks of processing time. A better technique would be to have an interrupt service routine buffer any characters that are coming in and have scanf() access the buffer only - if it is going to block for input then do it in such a way that allows other tasks to execute. For example, have the interrupt service routine give a semaphore when data is available, and implement the IO used by the scanf() function to block on the semaphore so it is unblocked only when data is ready to be processed.

FreeRTOS console IO is normally performed with FreeRTOS+CLI, and there are lots of examples of it being used in the FreeRTOS download. The examples all create another task to manage the command input, referring to one of the examples and the relevant documentation page will show you how to do this in a thread safe and multi-tasking friendly way.

Regards.

kamran99kamran wrote on Monday, March 17, 2014:

But why doesn’t scanf() work, even I have involved heap_2.c.
And about uart, this is related to FreeRTOS, which is making getchar work.
this is because it can read only one letter/sign !
How can i change the program of FreeRTOS in uart, to read more letter, before i
I confirm the Enter key on keyboard

kamran99kamran wrote on Monday, March 17, 2014:

how are you expecting scanf() to work in whichever C library you are using?
I am using newlib C library!!

Thank you very much, my problem was solved!
this was because of

xTaskCreate(UsartTask, (signed char*)“UsartTask”, 128, NULL, tskIDLE_PRIORITY+1, NULL)
and I changed from 128 to 1024. scanf() could do work!

rtel wrote on Monday, March 17, 2014:

I would recommend enabling the stack overflow hook function.

http://www.freertos.org/Stacks-and-stack-overflow-checking.html

I would also recommend making sure you are using a recent version and that configASSERT() is defined, as that will automatically check some of the more obscure but essential Cortex-M priority settings for you.

http://www.freertos.org/a00110.html#configASSERT

Regards.