본문으로 건너뛰기
cccskills
무료GitHub에 공개

dma-baremetal

Use when configuring DMA channels, circular buffer mode, double buffering, memory-to-peripheral transfers, or DMA IRQ completion on bare-metal MCUs. Not for cache theory: use cpu-cache-opt.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

설치 방법 보기

포함된 파일(2)

  • SKILL.md6.8 KB
  • agents/openai.yaml215 B

SKILL.md(원문)

설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.

DMA on bare metal

Contract

FieldBound contract
TriggerA UART, SPI, or ADC transfer must run without the CPU, an audio or sensor stream needs a double buffer, or a DMA transfer does not start or delivers corrupt data.
AuthorityRead-only: emits stream configuration, interrupt handling, and cache-maintenance sequences to chat; the user places them in the firmware. Rollback is not needed because no file is written. No remote mutation.
Side effectChat output only.
DoneThe stream and channel (or request line) are named from the reference manual request table, the register sequence configures the stream before enabling it, the interrupt handler clears the right flag register, and cache maintenance is stated for cores with a data cache.

Inputs

  • Target part and DMA controller type (STM32F4 stream and channel matrix, STM32L4 channel and request selection, STM32G0/G4/H7 DMAMUX, or another controller with its request table).
  • Direction: peripheral to memory, memory to peripheral, or memory to memory.
  • Peripheral data register address and data width.
  • Buffer address, length, and whether the buffer is single, circular, or double.
  • Whether the core has a data cache (Cortex-M7) and where the buffer lives.

Procedure

  1. Find the request mapping. On STM32F4 each peripheral request is fixed to a stream and channel pair in the DMA chapter's request table; USART2 RX is DMA1 Stream 5, Channel 4, and ADC1 is DMA2 Stream 0 or Stream 4, Channel 0. On DMAMUX parts the request is a number written to the mux channel. Done when: the stream and channel or request number are quoted from the table.

  2. Enable the DMA controller clock, make sure the stream is disabled, and configure it: peripheral address, memory address, count, direction, data sizes, memory increment, and interrupt enables. Set EN in a separate write after configuration; a stream still enabled ignores configuration writes. Done when: EN reads 0 before configuration and 1 after the final write.

    RCC->AHB1ENR |= RCC_AHB1ENR_DMA1EN;
    
    DMA1_Stream5->CR &= ~DMA_SxCR_EN;
    while (DMA1_Stream5->CR & DMA_SxCR_EN) { }
    
    DMA1_Stream5->PAR  = (uint32_t)&USART2->DR;
    DMA1_Stream5->M0AR = (uint32_t)rx_buf;
    DMA1_Stream5->NDTR = sizeof rx_buf;
    DMA1_Stream5->CR   = DMA_SxCR_CHSEL_2      /* channel 4 */
                       | DMA_SxCR_MINC         /* increment memory address */
                       | DMA_SxCR_TCIE;        /* transfer-complete interrupt */
                       /* DIR = 00: peripheral to memory; PSIZE, MSIZE = 00: byte */
    DMA1_Stream5->CR  |= DMA_SxCR_EN;
    
    USART2->CR3 |= USART_CR3_DMAR;             /* peripheral side must request DMA */
    
  3. Enable the request on the peripheral side. The DMA controller only moves data when the peripheral raises its request: DMAR or DMAT in USART_CR3, RXDMAEN or TXDMAEN in SPI_CR2, DMA in ADC_CR2. Done when: the peripheral's DMA enable bit is set and NDTR starts counting down.

  4. For continuous streams, set CIRC so NDTR reloads, and enable both the half-transfer and transfer-complete interrupts. Process the first half of the buffer in the half-transfer interrupt and the second half in the transfer-complete interrupt, so the CPU never reads the half the DMA is writing. For two separate buffers, use double-buffer mode (DBM with M1AR) where the controller supports it. Done when: the two interrupts alternate and each processes only its own half.

    DMA1_Stream5->CR |= DMA_SxCR_CIRC | DMA_SxCR_HTIE | DMA_SxCR_TCIE;
    
  5. Clear flags in the right register. On STM32F4, streams 0 to 3 report in LISR and clear through LIFCR; streams 4 to 7 report in HISR and clear through HIFCR. Write 1 to the flag bit to clear it; an unclear flag re-enters the handler at once. Done when: the handler reads the status register for its stream, clears exactly the flags it handled, and returns.

    void DMA1_Stream5_IRQHandler(void)
    {
        if (DMA1->HISR & DMA_HISR_HTIF5) {
            DMA1->HIFCR = DMA_HIFCR_CHTIF5;
            process(rx_buf, sizeof rx_buf / 2);
        }
        if (DMA1->HISR & DMA_HISR_TCIF5) {
            DMA1->HIFCR = DMA_HIFCR_CTCIF5;
            process(rx_buf + sizeof rx_buf / 2, sizeof rx_buf / 2);
        }
    }
    
  6. On a core with a data cache (Cortex-M7, STM32F7 and H7), keep the DMA buffer coherent. Either place the buffer in a region the MPU marks non-cacheable, or clean the cache before a memory-to-peripheral transfer and invalidate it after a peripheral-to-memory transfer. The CMSIS maintenance calls work on 32-byte lines, so align the buffer and round its size to 32 bytes. Done when: the buffer is in a non-cacheable region, or every transfer is bracketed by the matching maintenance call on an aligned range.

    SCB_CleanDCache_by_Addr((uint32_t *)tx_buf, (int32_t)sizeof tx_buf);       /* before TX */
    SCB_InvalidateDCache_by_Addr((uint32_t *)rx_buf, (int32_t)sizeof rx_buf);  /* after RX complete */
    
  7. Check that the memory the buffer lives in is reachable by the DMA master. On STM32F405 and F407 the 64 KB core-coupled memory at 0x10000000 is not on the DMA path; place buffers in SRAM1. Done when: the buffer address is inside a region the bus matrix figure connects to the DMA controller.

  8. Verify with a known pattern: fill the source, run one transfer, compare the destination, then run the circular case and confirm the interrupt sequence with a GPIO toggle or a counter. Done when: the data matches and the interrupt order is as designed.

Failure and recovery

SymptomCauseFix
Transfer never startsWrong stream or channel for the peripheral requestRe-read the request table; the pair is fixed per peripheral.
NDTR stays at its initial valuePeripheral DMA request not enabledSet DMAR, DMAT, RXDMAEN, TXDMAEN, or DMA on the peripheral.
Configuration writes ignoredStream was still enabledClear EN, wait for it to read 0, then configure.
Received data stale or partly oldData cache not invalidated on Cortex-M7Invalidate after RX complete, or make the region non-cacheable.
Handler re-enters continuouslyFlag not cleared or cleared in the wrong registerWrite the flag to LIFCR for streams 0 to 3 or HIFCR for 4 to 7.
Transfer error flag setBuffer in memory the DMA cannot reach, or misaligned for the data sizeMove the buffer to SRAM1; align to the data size.

Output

A stream configuration sequence for the target part with the request mapping quoted from the reference manual, the peripheral-side enable, the interrupt handler with the correct flag register, and the cache or placement rule for the buffer.

리뷰

아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.

댓글

로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.

아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.

보내면 바로 공개됩니다. 이메일 주소나 전화번호 같은 개인 정보는 쓰지 마세요. URL은 2개까지입니다.

0 / 1,000자

이 양식은 reCAPTCHA로 보호되며 Google 개인정보처리방침 및 서비스 약관이 적용됩니다.

같은 저장소의 스킬

Use when explaining System V AMD64, ARM AAPCS, RISC-V psABI, stack frames, variadic calls, or FFI register rules. Not for the Rust FFI binding layer: use rust-ffi.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

OutlineDriven/odin-claude-plugin372026년 9월 29일 업데이트

Use when configuring ADC sampling time, DMA-driven ADC, calibration, or DAC channel setup on bare-metal MCUs. Not for the DMA stream itself: use dma-baremetal.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

OutlineDriven/odin-claude-plugin372026년 9월 29일 업데이트

af-xdp

무료

Use when creating AF_XDP sockets, configuring UMEM and XSK rings, writing an XDP redirect program, or choosing copy versus zero-copy mode. Not for full kernel bypass: use dpdk.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

OutlineDriven/odin-claude-plugin372026년 9월 29일 업데이트

Use when a completed session needs an agent-environment retrospective. Not for an engineering retrospective from telemetry: use engineering-retrospective.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

OutlineDriven/odin-claude-plugin372026년 9월 29일 업데이트

Use when a redacted, trimmed agent transcript must be appended to a GitHub PR or issue body, with human approval and preview. Not for automated or model-initiated insertion.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

OutlineDriven/odin-claude-plugin372026년 9월 29일 업데이트

agents-md

무료

Use when a repo needs agent setup, AGENTS.md added or made lean, CLAUDE.md audited, or agent instructions scored or pruned. Not for remote, credential, publish, deploy, or irreversible changes.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

OutlineDriven/odin-claude-plugin372026년 9월 29일 업데이트

OutlineDriven의 스킬 모두 보기

이 스킬의 문제 신고