QUOTE (abutorin @ Jan 16 2013, 13:33)

Если с прерываниями стало ясно.то опять возникает вопрос в чем же тогда проблема?
Вы заводите в начале обработчика объект типа OS::TISRW (я в предыдущем сообщении описался, указав его как OS::TCritSect)? Без него прерывание не сможет при необходимости вызвать перепланирование.
QUOTE (abutorin @ Jan 16 2013, 13:33)

У меня логика построена на том, что я с уартом работаю как с потоком байт, я не знаю сколько байт отправляюи сколько получу. Если даже с таким подходом это можно реализовать через DMA то был бы очень признателен за пример.
Как-то так, хотя мне самому этот код не очень нравится:
CODE
//**** uart.h: *****
#ifndef UART_H__
#define UART_H__
#include <stdint.h>
#include <stm32f10x.h>
#include <scmRTOS.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
class uart
{
public:
uart(USART_TypeDef * usart, uint32_t dma_channel)
: Tx_ready(OS::TEventFlag::efOn)
, pUART(usart)
, DMA_channel_no(dma_channel - 1)
, DMA_channel((DMA_Channel_TypeDef *)(DMA1_Channel1_BASE + (dma_channel - 1) * 0x14))
{}
void send(const uint8_t &byte);
void send(char const * string);
void send(char * string, OS::TMutex * pLock);
void send_HEX(uint8_t data);
void send_HEX(uint16_t data);
void new_line();
void vprintf(char const * format, va_list args);
void printf(char const * format, ...);
bool is_transmitting() {return !(pUART->SR & USART_SR_TXE);}
bool hasinput() {return Rx_buffer.get_count();}
bool receive(uint8_t & data, timeout_t timeout);
bool receive(char & data, timeout_t timeout);
uint8_t receive() { uint8_t Data; Rx_buffer.pop(Data); return Data;}
void speed_setup(uint_fast32_t baudrate) { pUART->BRR = (PCLK1_FREQ + baudrate / 2) / baudrate; }
void tx_dma_handler();
void rx_handler();
protected:
static size_t const RX_BUFF_SIZE = 16;
OS::TEventFlag Tx_ready;
uint8_t Tx_byte_buffer;
OS::TMutex Tx_byte_buffer_lock;
OS::TMutex Tx_buffer_lock;
char Tx_buffer[80];
OS::TMutex * pDMA_buffer_lock;
void setup_tx_dma(uint8_t const * pSrc, size_t size, OS::TMutex *pLock = 0);
OS::channel<uint8_t volatile, RX_BUFF_SIZE> Rx_buffer;
private:
USART_TypeDef * pUART;
uint_fast32_t DMA_channel_no;
DMA_Channel_TypeDef * DMA_channel;
};
// =========== receiving ==============
INLINE void uart::rx_handler()
{
uint8_t Data = pUART->DR;
if(Rx_buffer.get_free_size())
Rx_buffer.push(Data);
}
inline bool uart::receive(uint8_t & symbol, timeout_t timeout)
{
if(timeout <= 0 || !Rx_buffer.pop(symbol, timeout))
return false;
return true;
}
inline bool uart::receive(char & symbol, timeout_t timeout)
{
uint8_t data;
if(timeout <= 0 || !Rx_buffer.pop(data, timeout))
return false;
symbol = char(data);
return true;
}
// ========== transmitting ===========
INLINE void uart::tx_dma_handler()
{
DMA1->IFCR = DMA_IFCR_CTCIF1 << (4 * DMA_channel_no);
DMA_channel->CCR = 0
;
Tx_ready.signal_isr();
if(pDMA_buffer_lock)
pDMA_buffer_lock->unlock_isr();
}
#endif //UART_H__
//**** uart.cpp ******
#include "uart.h"
#include <string.h>
void uart::setup_tx_dma(uint8_t const * pSrc, size_t size, OS::TMutex * pLock)
{
Tx_ready.wait();
pDMA_buffer_lock = pLock;
// --------- DMA setup -----------
DMA_channel->CPAR = uintptr_t(&pUART->DR);
DMA_channel->CMAR = uintptr_t(pSrc);
DMA_channel->CNDTR = size;
DMA_channel->CCR = 0
| 1 * DMA_CCR1_EN // Channel enable
| 1 * DMA_CCR1_TCIE // Transfer complete interrupt enable
| 0 * DMA_CCR1_HTIE // Half Transfer interrupt enable
| 0 * DMA_CCR1_TEIE // Transfer error interrupt enable
| 1 * DMA_CCR1_DIR // Data transfer direction: Memory->Peripheral
| 0 * DMA_CCR1_CIRC // Circular mode
| 0 * DMA_CCR1_PINC // Peripheral increment mode
| 1 * DMA_CCR1_MINC // Memory increment mode
| 0 * DMA_CCR1_PSIZE_0 // Peripheral size: 8 bits
| 0 * DMA_CCR1_MSIZE_0 // Memory size: 8 bits
| 1 * DMA_CCR1_PL_0 // Channel Priority level: higher than lowest, conversion frequency is low enough
| 0 * DMA_CCR1_MEM2MEM // Memory to memory mode disabled
;
}
void uart::send(uint8_t const &byte)
{
Tx_byte_buffer_lock.lock();
Tx_byte_buffer = byte;
setup_tx_dma(&Tx_byte_buffer, 1, &Tx_byte_buffer_lock);
}
void uart::send(char const * pString)
{
setup_tx_dma((uint8_t const *)pString, strlen(pString));
}
void uart::send(char * pString, OS::TMutex * pLock)
{
setup_tx_dma((uint8_t const *)pString, strlen(pString), pLock);
}
void uart::vprintf(char const * format, va_list args)
{
Tx_buffer_lock.lock();
vsprintf (Tx_buffer, format, args);
send(Tx_buffer, &Tx_buffer_lock);
}
void uart::printf(char const * format, ...)
{
va_list args;
va_start (args, format);
uart::vprintf (format, args);
va_end (args);
}
uart Serial(USART2, 7);
uart & Console = Serial;
extern "C" void DMA1_Channel7_IRQHandler(void)
{
OS::TISRW ISR_wrapper;
Console.tx_dma_handler();
}
extern "C" void USART2_IRQHandler(void)
{
OS::TISRW ISR_wrapper;
Console.rx_handler();
}
Тут готовность DMA передается через флаг Tx_ready, а буфер передачи (если он используется для данной посылки) защищен мутексом Tx_byte_buffer_lock. Если же передается готовая строка из флеша или ОЗУ - буфер не используется.