2013-02-17 5 views
5

STM32F3 mc (STM32F3-Discovery)에 대한 내장 코드를 작성하고 있습니다. 일부 데이터를 UART로 출력해야하며 DMA 전송을 위해 바이트 전송 완료를 기다리는 대신 센서 읽기 및 데이터 처리에 집중할 수 있도록 DMA를 사용하고 있습니다. 문제는 그러나 나는 결합해야한다는 것입니다 :순환 버퍼에 서식이 지정된 인쇄

  1. 형식화 된 출력 (즉 printf와의 일부)
  2. (이전 인쇄가 완료되기 전에 발생) 연속 인쇄

의 숫자 그래서 원형 버퍼에 대해 생각하고 있어요. 하지만 나는 버퍼의 끝을 존중하고 버퍼의 시작 부분에 계속 쓰기 위해 sprintf를 만드는 방법을 알지 못한다고 생각합니다. 물론 다른 임시 버퍼를 만들고 거기에 인쇄하고 바이트 단위로 복사 할 수는 있지만 나에게 우아하지는 않습니다.

+1

흥미로운 요구 사항이지만 '적절한 복사 기능으로 순환 버퍼에 이어 임시 버퍼로 포맷'보다 훨씬 더 잘할 것이라고 생각하지 않습니다. –

답변

2

하나의 해결책은 링 버퍼와 함께 작동 할 수있는 자신의 sprintf을 구현하는 것일 수 있습니다. 불행히도 이것은 기본적인 문제에 관해서는 도움이되지 않을 것입니다 : 링 버퍼가 꽉 차서 sprintf을 호출하면 어떻게 될까요?

메모리 상황이 그것을 줄 수있는 경우에, 나는이 문제에 대한 다른 해결책 좋을 것 : 아이디어는 버퍼의 두 가지 연결리스트 기반으로

를 (무료 버퍼에 대한 하나 개의 목록, 전송 큐와 같은 하나 개의리스트) . 버퍼의 크기는 동일하므로 최악의 길이의 문자열을 저장할 수 있습니다. 버퍼는 할당/할당 해제가 free 또는 전송 목록에서 요소를 대기열에서 풀거나 큐에 넣는 단순한 힙을 작성합니다.

동일한 크기의 버퍼를 사용하면 메모리를 동적으로 할당하는 동안 "checkerboarding"과 같은 외부 조각화 효과가 발생하지 않습니다. 이 작업을 위해 자체 힙을 구축하면 전송 작업에 사용할 수있는 총 버퍼 크기를 완벽하게 제어 할 수 있습니다. 다음과 같이

나는이 실행 상상할 수 :

  1. 당신은에 데이터를 렌더링하는 무료 목록에서 버퍼를 할당 할 수 있습니다.
  2. 는 DMA를 들어

를 전송 큐에 전송되는 데이터를 추가 (필요한 경우 전송을 트리거) 버퍼의 데이터를 렌더링하기 위해 렌더링 기능 (프로피온산, 글리콜의 sprintf와)를 사용하면 전송 전송 끝 IRQ를 처리합니다. 여기에서 방금 "무료 목록"으로 전송 된 버퍼를 이동하고 대기열의 다음 버퍼에 대한 전송을 설정합니다.

이 솔루션은 메모리가 가장 효율적이지는 않지만 메모리에 한 번만 쓰고 할당/할당 해제는 어딘가에 포인터를 가져 오거나 저장하는 것이므로 런타임 효율성이 좋습니다. 물론 할당/할당 해제를 위해 응용 프로그램과 IRQ간에 경쟁 조건을 얻지 않았는지 확인해야합니다.

어쩌면이 아이디어를 통해 요구 사항을 해결할 수 있습니다.

1

대략적인 방법은 printf 버퍼를 ringbuffer 크기의 2 배로 할당 한 다음 전반부를 링 버퍼로 사용하는 것입니다. 오버플로를 감지하고 후반부의 오버플로를 앞쪽 (고리 부분)으로 복사합니다.

void xprintf(const char *format, ...) 
{ 
    int written; 
    va_list args; 
    va_start(args, format); 
    written = vsnprintf(buffer, HALF_BUFFER_SIZE, format, args); 
    va_end(args); 
    if (buffer + written > bufferStart + HALF_BUFFER_SIZE) 
    { // time to wrap 
    int overflow = (buffer + written) - (bufferStart + HALF_BUFFER_SIZE); 
    memmove(bufferStart, bufferStart + HALF_BUFFER_SIZE, overflow; 
    buffer = bufferStart + overflow; 
    } 
} 
관련 문제