Вт июл 19, 2022 05:31:48
Вт июл 19, 2022 09:26:17
Вт июл 19, 2022 11:12:31
Ср июл 20, 2022 18:10:51
Ср июл 20, 2022 18:20:16
Ср июл 20, 2022 21:51:22
Чт июл 21, 2022 12:30:20
volatile uint8_t DMA_STATE;
#define DMA_tty0_TX_ACTIVE 0x01
uint8_t tty0_TX_BUF[1024];
volatile uint16_t tty0_TX_POS;
volatile uint16_t tty0_WR_POS;
void DMA2_Stream7_IRQHandler(void) {
// tty0 (отладочная консоль)
if (DMA2->HISR & DMA_HISR_TCIF7) {
DMA2->HIFCR = DMA_HIFCR_CTCIF7; // сброс флага события TCIF
DMA_STATE &= ~DMA_tty0_TX_ACTIVE;
tty0_ActivateDMA();
} else if (DMA2->HISR & DMA_HISR_HTIF7) {
DMA2->HIFCR = DMA_HIFCR_CHTIF7; // сброс флага события HTIF
} else if (DMA2->HISR & DMA_HISR_FEIF7) {
DMA2->HIFCR = DMA_HIFCR_CFEIF7; // сброс флага события FEIF
} else if (DMA2->HISR & DMA_HISR_DMEIF7) {
DMA2->HIFCR = DMA_HIFCR_CDMEIF7; // сброс флага события DMEIF
} else if (DMA2->HISR & DMA_HISR_TEIF7) {
DMA2->HIFCR = DMA_HIFCR_CTEIF7; // сброс флага события TEIF
};
};
void USART1_IRQHandler(void) {
uint8_t tmp;
while (USART1->SR & USART_SR_RXNE) {
tmp = USART1->DR;
if (DMA_STATE & DMA_tty0_thread_ready) {
#ifdef USE_FREERTOS
xQueueSendFromISR(Q_tty0, &tmp, 0);
#endif
} else {
microrl_insert_char(prl, tmp);
};
};
};
void tty0_ActivateDMA(void) {
uint16_t CurrWrPos = tty0_WR_POS;
uint16_t DataToSend;
DataToSend = 0;
if(!(DMA_STATE & DMA_tty0_TX_ACTIVE)) {
DMA2_Stream7->CR &= ~DMA_SxCR_EN; // Отключаем поток DMA
if (tty0_TX_POS != CurrWrPos) {
// Если не совпадает - значит, данные есть. Или малый шанс на переполнение буфера.
DMA2_Stream7->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;
};
DMA2_Stream7->NDTR = DataToSend;
DMA2_Stream7->FCR = 0;
USART1->SR = ~(USART_SR_TC);
// И только ПОСЛЕ этого включаем его. Да, странность. Но иначе он уходит в ошибку.
DMA2_Stream7->CR |= DMA_SxCR_EN;
DMA_STATE |= DMA_tty0_TX_ACTIVE;
};
}; // Если активен - сработает при вызове события завершения обмена.
};
// ---------- Аппаратно-зависимые функции - инициализпция ----------
void UpdateUSART_BR(void) {
static uint8_t PrescalerTable[8] = {1,1,1,1,2,4,8,16};
static uint16_t AHB_Presc[16] = {1,1,1,1,1,1,1,1,2,4,8,16,64,128,256,512};
uint8_t presc;
uint16_t APB_Presc;
SystemCoreClockUpdate();
APB_Presc = AHB_Presc[(RCC->CFGR >> 4) & 0x0F];
presc = PrescalerTable[(RCC->CFGR >> 13) & 0x07];
USART1->CR1 &= ~(USART_CR1_TE | USART_CR1_RE | USART_CR1_UE);
// Системная консоль / tty0 - 115200
USART1->BRR = (SystemCoreClock / 115200 / presc / APB_Presc); // Делим системную частоту на скорость порта, на делители APB и AHB, чтобы получить правильный делитель.
USART1->CR1 |= (USART_CR1_TE | USART_CR1_RE | USART_CR1_UE);
};
void InitUSART(void) {
GPIOB->MODER &= 0xFFFF0FFF; // GPIOB[6-7].MODER = 00 - Input
GPIOB->MODER |= 0x0000A000; // GPIOB[6-7].MODER = 10 - Alternate
GPIOB->AFR[0] &= 0xFFFFFFFF; // GPIOB[6-7].Alternate = 0 (Sys)
GPIOB->AFR[0] |= 0x77000000; // GPIOB[6-7].Alternate = 7 (USART1)
// Enable USART1 (tty0)
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
// Reset USART1
RCC->APB2RSTR |= RCC_APB2RSTR_USART1RST;
// UnReset USART1
RCC->APB2RSTR &= ~RCC_APB2RSTR_USART1RST;
USART1->CR2 = 0;
USART1->CR3 = 0;
// Сброс DMA
RCC->AHB1RSTR |= RCC_AHB1RSTR_DMA2RST | RCC_AHB1RSTR_DMA1RST;
RCC->AHB1RSTR &= ~(RCC_AHB1RSTR_DMA2RST | RCC_AHB1RSTR_DMA1RST);
// Enable DMA1 & DMA2.
RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN | RCC_AHB1ENR_DMA1EN;
// Config USART1 to DMA Operations and clear flags.
USART1->CR3 |= /*USART_CR3_DMAR |*/ USART_CR3_DMAT;
USART1->SR &= ~(USART_SR_TC/* | USART_SR_RXNE*/);
UpdateUSART_BR();
// Указываем периферию
DMA2_Stream7->PAR = (uint32_t)&(USART1->DR);
// Указываем память
DMA2_Stream7->M0AR = (uint32_t)&tty0_TX_BUF;
// DMA1:Stream1:Channel4 (HW Console RX): MemInc + P->M + Transfer Complete INT.
// DMA1_Stream1->CR = DMA_SxCR_CHSEL_2 | DMA_SxCR_MINC | DMA_SxCR_TCIE;
// DMA1:Stream3:Channel4 (HW Console TX): MemInc + M->P + Transfer Complete INT.
DMA2_Stream7->CR = DMA_SxCR_CHSEL_2 | DMA_SxCR_MINC | DMA_SxCR_DIR_0 | DMA_SxCR_TCIE;
NVIC_EnableIRQ(USART1_IRQn);
NVIC_SetPriority(USART1_IRQn, 0x04);
NVIC_SetPriority(DMA2_Stream7_IRQn, 0x03);
NVIC_EnableIRQ(DMA2_Stream7_IRQn);
// microrl_init (prl, console_put); // Инициализпция консоли Microtl
// microrl_set_complete_callback(prl, console_complete); // Выставляем callback "Дополнить!"
// microrl_set_execute_callback(prl, console_execute); // Добавляем callback на выполнение.
USART1->CR1 = (USART_CR1_TE | USART_CR1_RE | USART_CR1_RXNEIE | USART_CR1_UE);
};
// ---------- "Высокоуровневые" функции.
char char_to_hex(char value) {
if (value > 9)
return '7' + value;
return '0' + value;
};
uint8_t hchar_to_int(char value) {
if ((value >= '0') && (value <= '9')) {
return (value - '0');
};
if ((value >= 'A') && (value <= 'F')) {
return (value - 'A' + 0x0A);
};
if ((value >= 'a') && (value <= 'f')) {
return (value - 'a' + 0x0A);
};
return 0;
};
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();
};
void console_put_hex_dword(const uint32_t Data) {
char txt[9];
txt[0] = char_to_hex((Data >> 28) & 0x0F);
txt[1] = char_to_hex((Data >> 24) & 0x0F);
txt[2] = char_to_hex((Data >> 20) & 0x0F);
txt[3] = char_to_hex((Data >> 16) & 0x0F);
txt[4] = char_to_hex((Data >> 12) & 0x0F);
txt[5] = char_to_hex((Data >> 8) & 0x0F);
txt[6] = char_to_hex((Data >> 4) & 0x0F);
txt[7] = char_to_hex((Data) & 0x0F);
txt[8] = 0;
console_put(txt);
};
void console_put_hex_word(const uint16_t Data) {
char txt[5];
txt[0] = char_to_hex((Data >> 12) & 0x0F);
txt[1] = char_to_hex((Data >> 8) & 0x0F);
txt[2] = char_to_hex((Data >> 4) & 0x0F);
txt[3] = char_to_hex((Data) & 0x0F);
txt[4] = 0;
console_put(txt);
};
void console_put_hex_byte(const uint8_t Data) {
char txt[3];
txt[0] = char_to_hex((Data >> 4) & 0x0F);
txt[1] = char_to_hex((Data) & 0x0F);
txt[2] = 0;
console_put(txt);
};
void console_put_int(const uint32_t value) {
uint8_t txt[13];
txt[12] = 0;
console_put(utoa_builtin_div(value, (char *)txt));
};
Пт июл 22, 2022 19:25:04
Вс июл 24, 2022 05:21:07