Вс фев 06, 2022 13:05:12
uint8_t len =* string ;
Вс фев 06, 2022 13:08:09
uint8_t len =* string ;
Вс фев 06, 2022 17:07:12
Пн фев 07, 2022 06:54:13
Цифровая доставка
Скачать в течение 3 рабочих дней
Этот товар не подлежит отмене и возврату
3 192,00 €
Пн фев 07, 2022 07:19:10
Пн фев 07, 2022 07:56:00
Пн фев 07, 2022 08:03:06
Пн фев 07, 2022 08:48:09
Пн фев 07, 2022 11:21:08
Building RAM: ./Build/KeyBrain.elf
text data bss dec hex filename
41740 20 85052 126812 1ef5c ./Build/KeyBrain.elf
:~/MCU_Proj/STM32F030-EEPROM$ make
Compiling: startup_stm32f030x8.s
Compiling: system_stm32f0xx.c
Compiling: main.c
Compiling: diskio.c
Compiling: ff.c
Compiling: uSD_SPI.c
Building: ./debug/ee_rw.elf
text data bss dec hex filename
21568 1260 2776 25604 6404 ./debug/ee_rw.elf
Пн фев 07, 2022 17:43:55
Пн фев 21, 2022 18:31:13
volatile uint8_t DMA_STATE=0; // Флаг работы DMA
volatile uint32_t tty0_TX_POS=0; // Указатель позиции записи в буфер
volatile uint32_t tty0_WR_POS=0; // Указатель позиции чтения из буфера (DMA)
volatile uint8_t tty0_TX_BUF[32]={0}; // Размер буфера равным степени двойки, минимум 2
#define BUF_MASK (sizeof(tty0_TX_BUF)-1)
volatile uint32_t len_WR_POS;
volatile uint32_t poz_WR_POS;
#define DMA_tty0_TX_ACTIVE 1
void DMA1_Channel4_IRQHandler(){
if(DMA1->ISR & DMA_ISR_TCIF4){ // Tx
DMA1->IFCR = DMA_IFCR_CTCIF4; // clear TC flag
DMA1_Channel4->CCR &= ~DMA_CCR1_EN; // Отключаем поток DM
DMA_STATE &= ~DMA_tty0_TX_ACTIVE;
while(len_WR_POS--){
poz_WR_POS--;
tty0_TX_BUF[poz_WR_POS & BUF_MASK]=0;
}
tty0_ActivateDMA();
}
}
void tty0_ActivateDMA(void) {
uint32_t CurrWrPos = tty0_WR_POS;
uint32_t DataToSend;
uint32_t mask = tty0_TX_POS & BUF_MASK;
uint32_t curr = CurrWrPos & BUF_MASK;
DataToSend = 0;
if(!(DMA_STATE & DMA_tty0_TX_ACTIVE)) {
DMA1_Channel4->CCR &= ~DMA_CCR1_EN; // Отключаем поток DMA
if (tty0_TX_POS != CurrWrPos) {
// Если не совпадает - значит, данные есть. Или малый шанс на переполнение буфера.
DMA1_Channel4->CMAR = (uint32_t)&(tty0_TX_BUF[mask]);
if ((mask) < (curr)) {
// Нет перехода через конец буфера
DataToSend = (CurrWrPos - tty0_TX_POS);
tty0_TX_POS = CurrWrPos;
} else {
// Нужно сделать кольцо.
DataToSend = (sizeof(tty0_TX_BUF) - (mask));
tty0_TX_POS += DataToSend;
};
len_WR_POS = DataToSend;
poz_WR_POS = (tty0_TX_POS & BUF_MASK);
DMA1_Channel4->CNDTR = DataToSend;
USART1->SR = ~(USART_SR_TC);
// И только ПОСЛЕ этого включаем его. Да, странность. Но иначе он уходит в ошибку.
DMA1_Channel4->CCR |= DMA_CCR1_EN;
DMA_STATE |= DMA_tty0_TX_ACTIVE;
};
}; // Если активен - сработает при вызове события завершения обмена.
};
// Принимаем СТРОКУ символов с нуль-терминатором.
void console_put(const char *text) {
while(*text) {
// Пока не нуль-терминатор
while(tty0_TX_BUF[tty0_WR_POS & BUF_MASK]) { }; // цикл ожидания с проверкой на \0
tty0_TX_BUF[tty0_WR_POS & BUF_MASK] = *text; // Копируем данные в буфер
text++; // Сдвигаем указатель текста.
tty0_WR_POS++; // Сдвигаем указатель на 1 байт дальше.
if((tty0_WR_POS & BUF_MASK) == 0) tty0_ActivateDMA();
};
// Запускаем.
tty0_ActivateDMA();
};
uint32_t start = DWT->CYCCNT;
SEND("\r\n");
printu(ms_tick);
SEND("\r\n");
SEND("\r\nSystem Frequency: ");
printu(SystemCoreClock);
SEND(" MHz \r\n");
SEND("\r\n STM32F100RB USART DMA-tx !!! 31");
SEND("\r\n STM32F100RB USART DMA-tx !!! 32");
SEND("\r\n STM32F100RB USART DMA-tx !!! 33");
SEND("\r\n");
printu(ms_tick);
SEND("\r\n");
uint32_t end = DWT->CYCCNT;
delay_ms(2000);
SEND("\r\nstart-end = ");
printu(end - start);
SEND("\r\n");
delay_ms(2000);
uint32_t start_h = DWT->CYCCNT;
SEND("Hello, world!\r\n");
uint32_t end_h = DWT->CYCCNT;
delay_ms(2000);
SEND("\r\nstart_h-end_h = ");
printu(end_h - start_h);
SEND("\r\n");
delay_ms(4000);
uint32_t start_m = DWT->CYCCNT;
SEND("... строка длиною 627 символов ...");
uint32_t end_m = DWT->CYCCNT;
delay_ms(2000);
SEND("\r\nstart_m-end_m = ");
printu(end_m - start_m);
SEND("\r\n");
#define BUFFER_SIZE 512
volatile uint16_t Buffer[BUFFER_SIZE]={0};
void test (void){
SEND("\r\n");
printu(ms_tick);
SEND("\r\n");
for (uint16_t i = 1000; i<(1000+BUFFER_SIZE); i++){
Buffer[i-1000] = i;
}
SEND("\r\n");
printu(ms_tick);
SEND("\r\n");
for (uint16_t i = 0; i<BUFFER_SIZE; i++){
printu(Buffer[i]);
SEND(" ");
}
SEND("\r\n");
SEND("\r\n");
printu(ms_tick);
SEND("\r\n");
}
Пн фев 21, 2022 19:08:42
Вт фев 22, 2022 21:41:56
Нет, это не нормально, только представьте, что было бы с жестким диском компа или еще с чем.AlanDrakes писал(а):Фактически, в буфер данные были положены, но их затёрло свежими. И это нормально для кольцевого буфера.
#define MAX_DMA_BUFFERS_COUNT 64
char BoxCon_RX_BUF[MAX_DMA_BUFFERS_COUNT]={0};
volatile uint8_t DMA_BUF_START[MAX_DMA_BUFFERS_COUNT]={0};
volatile uint8_t DMA_BUF_END[MAX_DMA_BUFFERS_COUNT]={0};
volatile uint8_t DMA_CURR_WR_BUF = 0;
char buff[MAX_DMA_BUFFERS_COUNT] = {0};
void USART1_IRQHandler(){
if (USART1->SR & USART_SR_IDLE) {
(void)USART1->DR; // Очистка флага IDLE. Мне лично кажется такой подход странным.
static uint32_t DMA_BUF_START_LAST = 0; // Устранен Warning[Pa082]: undefined behavior: the order of volatile accesses is undefined in this statement
if ((sizeof(BoxCon_RX_BUF) - DMA1_Channel5->CNDTR) != DMA_BUF_START_LAST) {
DMA_BUF_START[DMA_CURR_WR_BUF] = DMA_BUF_START_LAST;
DMA_BUF_START_LAST = (sizeof(BoxCon_RX_BUF) - DMA1_Channel5->CNDTR);
DMA_BUF_END[DMA_CURR_WR_BUF] = DMA_BUF_START_LAST;
DMA_CURR_WR_BUF++;
if (DMA_CURR_WR_BUF >= (MAX_DMA_BUFFERS_COUNT-1)) { DMA_CURR_WR_BUF = 0; };
};
}
}
while(1)
{ static uint8_t DMA_CURR_RD_BUF = 0; // Устранен Warning[Pa082]: undefined behavior: the order of volatile accesses is undefined in this statement
while (DMA_CURR_RD_BUF != DMA_CURR_WR_BUF) {
uint8_t b_start = DMA_BUF_START[DMA_CURR_RD_BUF]; // Копируем позиции начала
uint8_t b_end = DMA_BUF_END[DMA_CURR_RD_BUF]; // И конца буфера
// Переводим на следующий (но не проверяем его данные)
DMA_CURR_RD_BUF++;
if (DMA_CURR_RD_BUF >= (MAX_DMA_BUFFERS_COUNT-1)) DMA_CURR_RD_BUF = 0;
// сборка команды
uint8_t len_buff = strlen(buff); // определяем длину
if(b_start < b_end) {
uint32_t len = b_end-b_start;
if((len_buff+len)>(MAX_DMA_BUFFERS_COUNT-2)) len_buff=0;
memcpy(&buff[len_buff],&BoxCon_RX_BUF[b_start],len);
buff[len_buff+len]=0;
}
if(b_start > b_end) {
uint32_t len = MAX_DMA_BUFFERS_COUNT-b_start;
memcpy(&buff[len_buff],&BoxCon_RX_BUF[b_start],len);
memcpy(&buff[len],BoxCon_RX_BUF,b_end);
buff[len_buff+len+b_end]=0;
}
len_buff = strlen(buff)-1; // определяем длину
// если BkSp - сдвигаем назад
if((buff[len_buff] == 0x08)|| (buff[len_buff] == 0x7f)){
// стираем символ
// но не левее начала буфера
if(len_buff > 0) buff[len_buff-1]=0; else buff[len_buff]=0;
}
// если Enter - ввод закончен
if(((buff[len_buff] == '\n') || (buff[len_buff] == '\r'))) {
flag=1; buff[len_buff]=0; // стираем символ Enter, заменяем концом строки \0
}
}
static bool respcmp(char *s, const char *resp)
{
while(*resp)
if(*resp++ != *s++) return false;
return true;
}
static uint32_t my_atoi(char *str)
{
int result = 0;
if ('0'>*str || *str>'9')
{
str++;
}
while (*str != '\0')
{
if ('0'> *str || *str>'9')
break;
else
result = result * 10 + (*str++ - '0');
}
return result;
}
// поиск обработчика
if (flag) {
if (respcmp(buff, "LED ON")) {
GPIOC - > ODR |= GPIO_Pin_9;
SEND("\r\nLED ON\r\n");
}
if (respcmp(buff, "LED OFF")) {
GPIOC - > ODR &= ~GPIO_Pin_9;
SEND("\r\nLED OFF\r\n");
}
if (respcmp(buff, "B")) {
GPIOC - > ODR |= GPIO_Pin_8;
SEND("\r\nLED blue ON\r\n");
}
if (respcmp(buff, "S")) {
GPIOC - > ODR &= ~GPIO_Pin_8;
SEND("\r\nLED blue OFF\r\n");
}
if (respcmp(buff, "TOGGLE")) {
GPIOC - > ODR ^= GPIO_Pin_9;
}
if (respcmp(buff, "PRINT")) {
SEND("\r\nPRINT= ");
printu(main_p);
SEND("\r\n");
}
if (respcmp(buff, "COUNT=")) {
main_p = my_atoi(buff + sizeof("COUNT=") - 1);
}
//if (!strcmp (buff, "LED ON")) { GPIOC->ODR |= GPIO_Pin_9; SEND("\r\nLED ON\r\n"); }
//if (!strcmp (buff, "LED OFF")) { GPIOC->ODR &= ~GPIO_Pin_9; SEND("\r\nLED OFF\r\n"); }
//if (!strcmp (buff, "TOGGLE")) { GPIOC->ODR ^= GPIO_Pin_9; }
//sscanf(buff, "COUNT=%lu", &main_p);
//if (!strcmp (buff, "B")) { GPIOC->ODR |= GPIO_Pin_8; SEND("\r\nLED blue ON\r\n"); }
//if (!strcmp (buff, "S")) { GPIOC->ODR &= ~GPIO_Pin_8; SEND("\r\nLED blue OFF\r\n"); }
buff[0] = 0;
flag = 0;
SEND("\nCMD > ");
}
} //while(1)
Ср фев 23, 2022 06:16:38
Нет, это не нормально, только представьте, что было бы с жестким диском компа или еще с чем.AlanDrakes писал(а):Фактически, в буфер данные были положены, но их затёрло свежими. И это нормально для кольцевого буфера.
Ср фев 23, 2022 08:21:54
Опять же подходим к тому условию - если есть куча свободной оперативки. Вот f030 мне не хватило оперативки, а хочется не большой выигрыш, пусть и маленький, но выигрыш.AlanDrakes писал(а):Собственно, костыль.