Ковыряю сейчас STM32 с libopencm3. Попытался расширить пример usart_irq (наверное, нужно было ещё посмотреть на usart_irq_printf, но его я пока не открывал). Теперь у меня есть буфер для отправки и для приёма строк.
Кода не очень много, потому, думаю, можно выложить весь.
#include <string.h>
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/usart.h>
#include <libopencm3/cm3/nvic.h>
#define BS 16           // buffer size (number of strings)
char request[256];      // string to send to modem
char response[BS][256]; // last BS strings received from modem
int row, ch;            // number of string and last character received from modem
uint8_t last = 'A';     // last character received from modem
int step = 0;
static void clock_setup(void) {
    rcc_clock_setup_in_hse_8mhz_out_72mhz();
    /* Enable clocks for GPIO port A (for GPIO_USART1_TX) and USART1. */
    rcc_periph_clock_enable(RCC_GPIOA);
    rcc_periph_clock_enable(RCC_AFIO);
    rcc_periph_clock_enable(RCC_USART1);
}
static void usart_setup(void) {
    /* Enable the USART1 interrupt. */
    nvic_enable_irq(NVIC_USART1_IRQ);
    /* Setup GPIO pin GPIO_USART1_RE_TX on GPIO port A for transmit. */
    gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
              GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART1_TX);
    /* Setup GPIO pin GPIO_USART1_RE_RX on GPIO port A for receive. */
    gpio_set_mode(GPIOA, GPIO_MODE_INPUT,
              GPIO_CNF_INPUT_FLOAT, GPIO_USART1_RX);
    /* Setup UART parameters. */
    usart_set_baudrate(USART1, 115200);
    usart_set_databits(USART1, 8);
    usart_set_stopbits(USART1, USART_STOPBITS_1);
    usart_set_parity(USART1, USART_PARITY_NONE);
    usart_set_flow_control(USART1, USART_FLOWCONTROL_NONE);
    usart_set_mode(USART1, USART_MODE_TX_RX);
    /* Enable USART1 Receive interrupt. */
    USART_CR1(USART1) |= USART_CR1_RXNEIE;
    /* Finally enable the USART. */
    usart_enable(USART1);
}
static void gpio_setup(void) {
    gpio_set(GPIOA, GPIO1);
    /* Setup GPIO1 (in GPIO port A) for LED use. */
    gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ,
              GPIO_CNF_OUTPUT_PUSHPULL, GPIO1);
}
static void wait(void) {
    int i;
	for (i = 0; i < 800000; i++)	/* Wait a bit. */
		__asm__("nop");
}
static int row_num(int n) {
    // use this function to get correct row offset
    // row_num(0) - latest row, row_num(1) - second latest row, etc.
    int r = row - n;
    if (r < 0) {
        return r + BS;
    } else {
        return r;
    }
}
static void action_select(void) {
    if (strcmp(response[row], "OK") == 0) {
        gpio_toggle(GPIOA, GPIO1);
        wait();
        gpio_toggle(GPIOA, GPIO1);
        wait();
        gpio_toggle(GPIOA, GPIO1);
        wait();
        gpio_toggle(GPIOA, GPIO1);
    } else if (strcmp(response[row], "ERROR") == 0) {
        gpio_toggle(GPIOA, GPIO1);
        wait();
        gpio_toggle(GPIOA, GPIO1);
    } else if (strcmp(response[row], "PRINT") == 0) {
        int i;
        strcpy(request, "\r\n");
        for (i = 0; i < BS; i++) {
            char num[5] = { '[', i < 10 ? '0' + i : 'A' + i - 10, ']', ':', ' ' };
            strcat(request, num);
            strcat(request, response[row_num(i)]);
            strcat(request, "\r\n");
        }
    }
}
static void set_send(void) {
    /* Enable transmit interrupt so it sends back the data. */
    USART_CR1(USART1) |= USART_CR1_TXEIE;
}
static void unset_send(void) {
    /* Disable the TXE interrupt as we don't need it anymore. */
    USART_CR1(USART1) &= ~USART_CR1_TXEIE;
}
static void send(void) {
    if (request[0] != 0) {
        int i = 0;
        uint8_t s = '0';
        while (s = request[i++], s != 0) {
            usart_wait_send_ready(USART1);
            usart_send(USART1, s);
        }
        usart_wait_send_ready(USART1);
        usart_send(USART1, '\r');
        // new line here should be commented out in production
        usart_wait_send_ready(USART1);
        usart_send(USART1, '\n');
        request[0] = 0;
    } else {
        // echo last char back (should also be commented out in production)
        usart_wait_send_ready(USART1);
        usart_send(USART1, last);
        if (last == '\r') {
            usart_wait_send_ready(USART1);
            usart_send(USART1, '\n');
        }
    }
    unset_send();
}
static void receive(void) {
    /* Retrieve the data from the peripheral. */
    last = usart_recv(USART1);
    response[row][ch] = last;
    if (response[row][ch] == '\r') {
        response[row][ch] = '\0';
        action_select();
        if (ch > 1) row++;
        ch = 0;
        if (row == BS) row = 0; 
    } else if (response[row][ch] != '\n') {
        ch++;
    }
    set_send();
}
void usart1_isr(void) {
    /* Check if we were called because of RXNE. */
    if (((USART_CR1(USART1) & USART_CR1_RXNEIE) != 0) &&
        ((USART_SR(USART1) & USART_SR_RXNE) != 0)) {
        receive();
    }
    /* Check if we were called because of TXE. */
    if (((USART_CR1(USART1) & USART_CR1_TXEIE) != 0) &&
        ((USART_SR(USART1) & USART_SR_TXE) != 0)) {
        send();
    }
}
static void send_request(char *str) {
    strcpy(request, str);
    send();
}
int main(void) {
    clock_setup();
    gpio_setup();
    usart_setup();
    gpio_set(GPIOA, GPIO1);
    send_request("HELLO\r");
    /* Wait forever and do nothing. */
    while (1)
        __asm__("nop");
    return 0;
}
HELLO
OK
ERROR
PRINT
[0]: PRINT
[1]: ERROR
[2]: OK
[3]: 
[4]: 
[5]: 
[6]: 
[7]: 
[8]: 
[9]: 
[A]: 
[B]: 
[C]: 
[D]: 
[E]: 
[F]: 
Я подумал, что достаточно после инициализации в main добавить следующее:
    gpio_set(GPIOA, GPIO1);
    send_request("HELLO\r");
    while (strcmp(response[row_num(0)], "WORLD") != 0)
        __asm__("nop");
    gpio_clear(GPIOA, GPIO1);
    send_request("TRUE\r");
HELLO
WORLD
PRINT
[0]: 
     PRINT
[1]: 
     WORLD
[2]: 
[3]: 
[4]: 

 ncrmnt,
ncrmnt,   KivApple,
KivApple,   RiseOfDeath. И подскажите форум, где такие вопросы не будут оффтопиком.
RiseOfDeath. И подскажите форум, где такие вопросы не будут оффтопиком.


