Спойлер
Код: Выделить всё
Это не так. Дал команду на передачу и забыл.Код: Выделить всё
Это не так. Дал команду на передачу и забыл.Вот это и имел ввиду: больше телодвижений на подготовку буфера и включение канала.VladislavS писал(а):Откройте для себя strlen.
Код: Выделить всё
void Send_str_USART1_DMA(const char *adr)
{
constexpr uint32_t dma_cfg = _VAL2FLD(DMA_CCR_MSIZE, 0) | _VAL2FLD(DMA_CCR_PSIZE, 0) | DMA_CCR_DIR | DMA_CCR_MINC;
DMA1_Channel1->CCR = dma_cfg;
DMA1_Channel1->CMAR = (uint32_t) adr;
char *p = (char *)adr;
while(*p) p++;
DMA1_Channel1->CNDTR = p-adr;
DMA1_Channel1->CCR = dma_cfg | DMA_CCR_EN;
}Код: Выделить всё
Используется прерывание USART:IDLE,Код: Выделить всё
void InitUART(void) {
<...>
USART1->CR2 = 0;
USART1->CR3 = 0;
USART1->BRR = (SystemCoreClock / 38400 / presc / APB_Presc); // Делим системную частоту на скорость порта, на делители APB и AHB, чтобы получить искомое значение регистра.
USART1->CR1 = (USART_CR1_TE | USART_CR1_RE | USART_CR1_IDLEIE);
USART1->CR3 |= USART_CR3_DMAR | USART_CR3_DMAT;
USART1->SR &= ~(USART_SR_TC | USART_SR_RXNE);
DMA2_Stream5->PAR = (uint32_t)&(USART1->DR);
DMA2_Stream7->PAR = (uint32_t)&(USART1->DR);
DMA2_Stream5->M0AR = (uint32_t)&BoxCon_RX_BUF;
DMA2_Stream7->M0AR = (uint32_t)&BoxCon_TX_BUF;
DMA2_Stream5->CR = DMA_SxCR_CHSEL_2 | DMA_SxCR_MINC | DMA_SxCR_CIRC;
DMA2_Stream7->CR = DMA_SxCR_CHSEL_2 | DMA_SxCR_MINC | DMA_SxCR_DIR_0 | DMA_SxCR_TCIE;
NVIC_EnableIRQ(DMA2_Stream7_IRQn);
NVIC_SetPriority(DMA2_Stream7_IRQn, 0x04);
NVIC_EnableIRQ(USART1_IRQn);
NVIC_SetPriority(USART1_IRQn, 0x02);
};
int main(void) {
InitVariables();
NVIC_SetPriorityGrouping(3); // Инициализация NVIC - 4 bits for pre-emption priority, 0 - subgroups
SysInit(); // Настройка отладки, переключение на высокую тактовую частоту.
DWT_Init(); // Настройка микросекундного таймера
InitIO(); // Настройка портов IO
InitUART(); // Настройка UART
InitDMA(); // Настройка DMA
<...>
xTaskCreate(vTaskHWCon, ( const char * ) "HWCon", 256, NULL, 2, &Task_HWCon);
<...>
vTaskStartScheduler();
};
void USART1_IRQHandler(void) {
if (USART1->SR & USART_SR_IDLE) {
(void)USART1->DR; // Очистка флага IDLE. Мне лично кажется такой подход странным.
BOX_CON_RX_DONE = 1;
if ((sizeof(BoxCon_RX_BUF) - DMA2_Stream5->NDTR) != DMA_BUF_START_LAST) {
DMA_BUF_START[DMA_CURR_WR_BUF] = DMA_BUF_START_LAST;
DMA_BUF_START_LAST = (sizeof(BoxCon_RX_BUF) - DMA2_Stream5->NDTR);
DMA_BUF_END[DMA_CURR_WR_BUF] = DMA_BUF_START_LAST;
DMA_CURR_WR_BUF++;
if (DMA_CURR_WR_BUF >= (MAX_DMA_BUFFERS_COUNT)) { DMA_CURR_WR_BUF = 0; };
};
};
};
void vTaskHWCon (void *pvParameters) {
<...>
USART1->CR1 |= USART_CR1_UE; // Enable box console.
<...>
while(1) {
<...>
while (DMA_CURR_RD_BUF != DMA_CURR_WR_BUF) {
CPU_LED_BLINK(CPU_LEDS_HWCON);
b_start = DMA_BUF_START[DMA_CURR_RD_BUF]; // Копируем позиции начала
b_end = DMA_BUF_END[DMA_CURR_RD_BUF]; // И конца буфера
// Переводим на следующий (но не проверяем его данные)
DMA_CURR_RD_BUF++;
if (DMA_CURR_RD_BUF >= (MAX_DMA_BUFFERS_COUNT)) DMA_CURR_RD_BUF = 0;
<...>
};
BOX_CON_RX_DONE = 0; // Сбрасываем флаг.
vTaskDelay(1); // Сообщаем Scheduler'у, что сейчас нам делать нечего.
};
};
конечноVladislavS писал(а):Вы это серьёзно?
Код: Выделить всё
while(*p) p++;Код: Выделить всё
// +1 из-за уменьшения sizeOfBuff для отлова кадров длиной
// больше 256 байт.
rxCnt = rx_n - ( dma_stream_rx -> NDTR );
Это Вы кому ?tonyk писал(а):Вы читаете, что вам пишут, а?
Что-то я в РМ нигде не нахожу ничего про этот IDLE и условия его возникновения. Хоть бы диаграммку какую нарисовали.tonyk писал(а):Устанавливается строго после 20 идущих подряд единичных бит в линии
Ты RM почитай, а потом выводы делай.Аlex писал(а):Судя по всему, если мы будем ловить от него прерывания, то оно будет постоянно вылетать, через каждые 20 бит, пока на RX тишина. Это же жесть, дёргать постоянно проц без повода
Я выводы сделал из твоих слов :tonyk писал(а):Ты RM почитай, а потом выводы делай.
tonyk писал(а):Устанавливается строго после 20 идущих подряд единичных бит в линии.
VladislavS писал(а):Я делаю упор на думать головой.
Как я и сказал: Вы делаете упор на тактовую частоту мк.VladislavS писал(а): При частоте процессор 100 МГц
Будем рассматривать альтернативные варианты для каждого случая?VladislavS писал(а):И после этого на strlen экономить.
Код: Выделить всё
for (uint16_t i = 0; i<BUFFER_SIZE; i++){
printu(Buffer[i]);
usart_send_str(" ");
}
usart_send_str("\r\n");Код: Выделить всё
void printu(uint32_t val)
{
char bufa[11], bufb[10];
int l = 0, bpos = 0;
if(!val){
bufa[0] = '0';
l = 1;
}else{
while(val){
bufb[l++] = val % 10 + '0';
val /= 10;
}
int i;
bpos += l;
for(i = 0; i < l; ++i){
bufa[--bpos] = bufb[i];
}
}
bufa[l + bpos] = 0;
usart_send_str(bufa);
}
Код: Выделить всё
void usart_send_str(char* str)
{
while(*str) {
while ((USART1->ISR & USART_ISR_TXE) == 0) {}
USART1->TDR = *str++;
}
}Код: Выделить всё
void tty0_ActivateDMA(void) {
uint16_t CurrWrPos = tty0_WR_POS;
uint16_t DataToSend;
DataToSend = 0;
if(!(DMA_STATE & DMA_tty0_TX_ACTIVE)) {
DMA1_Stream3->CR &= ~DMA_SxCR_EN; // Отключаем поток DMA
if (tty0_TX_POS != CurrWrPos) {
// Если не совпадает - значит, данные есть. Или малый шанс на переполнение буфера.
DMA1_Stream3->M0AR = (uint32_t)&(tty0_TX_BUF[tty0_TX_POS]);
if (tty0_TX_POS < CurrWrPos) {
// Нет перехода через конец буфера
DataToSend = (CurrWrPos - tty0_TX_POS);
tty0_TX_POS = CurrWrPos;
} else {
// Нужно сделать кольцо.
DataToSend = (sizeof(tty0_TX_BUF) - tty0_TX_POS);
tty0_TX_POS = 0;
};
DMA1_Stream3->NDTR = DataToSend;
DMA1_Stream3->FCR = 0;
USART3->SR = ~(USART_SR_TC);
// И только ПОСЛЕ этого включаем его. Да, странность. Но иначе он уходит в ошибку.
DMA1_Stream3->CR |= DMA_SxCR_EN;
};
}; // Если активен - сработает при вызове события завершения обмена.
};
// Принимаем СТРОКУ символов с нуль-терминатором.
void console_put(const char *text) {
while(*text) {
// Пока не нуль-терминатор
tty0_TX_BUF[tty0_WR_POS] = *text; // Копируем данные в буфер
text++; // Сдвигаем указатель текста.
tty0_WR_POS++; // Сдвигаем указатель на 1 байт дальше.
if (tty0_WR_POS >= sizeof(tty0_TX_BUF)) tty0_WR_POS = 0; // Указатель должен быть в пределах допустимых значений.
};
// Запускаем.
tty0_ActivateDMA();
};
int main(void) {
<...>
InitIO(); // Настройка портов IO
InitUART(); // Настройка UART
InitDMA(); // Настройка DMA
console_timestamp();
console_put("System Frequency: ");
console_put_int(SystemCoreClock / 1000000);
console_put("MHz\r\n");
console_timestamp();
console_put("Initializing RTC.\r\n");
};