You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

树莓派Circle框架下绘制特定ASCII字符触发屏幕闪烁故障排查求助

树莓派Circle框架下绘制特定ASCII字符触发屏幕闪烁故障排查求助

大家好,我现在在做一个基于树莓派Compute Module 4的个人项目,用Circle框架开发,遇到了一个非常奇怪的屏幕显示问题:当我绘制32个及以上特定字符时,这些字符之后的所有像素都会出现画面 glitch。

我使用的是固定宽度(2字节)的位图字体,每个字符由characterHeight行的u16数据表示,高位在前。目前测试发现,数字、?、@、所有大写字母以及小写a都会触发这个故障,但像:、`这类字符就不会出现问题。

以下是我的关键代码:

drawChar函数

void drawChar(MemoryBuffer& buffer, const Font& font, char character, u32 posX, u32 posY, u32 color) {
    // y represents position in character
    for(u32 y = 0; y < font.characterHeight; ++y) {
        // Current line is character * characterHeight + y because char*charHeight gets you to the correct array and + y gets you to the correct line in the array
        u16 currLine = font.font[character * font.characterHeight + y];
        // x represents position in character
        for(u32 x = 0; x < font.characterWidth; ++x) {
            // currLine anded with 1 shifted over characterWidth - 1 - x bits because 1 << characterWidth - 1 places the 1 at the beginning of line, then - x moves it over x bits
            if(currLine & (1 << (font.characterWidth - 1 - x)))
                buffer.DrawPixel(x + posX, y + posY, color);
        }
    }
}

drawPixel函数

void MemoryBuffer::DrawPixel(u32 x, u32 y, u32 color) {
    m_BufferPointer[y * (m_Pitch / 4) + x] = color;
}

为了方便排查,我整理了最小复现示例代码:

kernel.h

#ifndef _kernel_h
#define _kernel_h

#include "HDMIDraw.h"
#include <circle/types.h>
#include <circle/bcmframebuffer.h>

enum TShutdownMode {
    ShutdownNone,
    ShutdownHalt,
    ShutdownReboot
};

class CKernel {
public:
    CKernel (void);
    ~CKernel (void);
    boolean Initialize (void);
    TShutdownMode Run (void);
private:
    CBcmFrameBuffer m_FrameBuffer;
    MemoryBuffer m_VirtBuffer;
};

#endif

kernel.cpp

#include "kernel.h"
#include "text.h"

const Font FontTerminus = {.font= &font16x32norm[0][0], .characterWidth = 16, .characterHeight = 32};

CKernel::CKernel (void)
    : m_FrameBuffer(0, 0, 32) {
}

CKernel::~CKernel (void) {
}

boolean CKernel::Initialize (void) {
    if (!m_FrameBuffer.Initialize())
        return FALSE;

    u32 width = m_FrameBuffer.GetWidth();
    u32 height = m_FrameBuffer.GetHeight();
    u32 pitch = m_FrameBuffer.GetPitch();

    m_VirtBuffer.Allocate(width, height, pitch);

    return TRUE;
}

TShutdownMode CKernel::Run (void) {
    // Display loop
    while (true) {
        // Fill screen white (blank screen at start of loop)
        m_VirtBuffer.FillScreen(0xFFFFFF);

        // Draw a colored box, and test string
        m_VirtBuffer.DrawRect(0, 0, m_VirtBuffer.GetWidth()/2, m_VirtBuffer.GetHeight()/2, 0x00FF00);
        m_VirtBuffer.DrawString(FontTerminus, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 0, 0, 0x000000);

        // Copy m_VirtBuffer (the draw buffer) to m_FrameBuffer (the display buffer), then wait for vsync to avoid tearing
        m_VirtBuffer.CopyToFrameBuffer(m_FrameBuffer);
        m_FrameBuffer.WaitForVerticalSync();

        // Ensure clean display
    }

    return ShutdownHalt;
}

HDMIDraw.h

#ifndef _hdmi_draw
#define _hdmi_draw

#include <circle/bcmframebuffer.h>
#include <circle/types.h>

struct Font;

struct Bitmap {
    const u32* pixelMap;
    const u32 width;
    const u32 height;
    constexpr Bitmap(const u32* pixels, u32 w, u32 h) : pixelMap(pixels), width(w), height(h) {}
};

class MemoryBuffer {
public:
    MemoryBuffer();
    ~MemoryBuffer();
    void Allocate(u32 Width, u32 Height, u32 Pitch);
    u32* GetBuffer() { return m_BufferPointer; }
    u32 GetPitch() const { return m_Pitch; }
    u32 GetWidth() const { return m_Width; }
    u32 GetHeight() const { return m_Height; }
    void DrawPixel(u32 x, u32 y, u32 color);
    void FillScreen(u32 color);
    void DrawRect(u32 x1, u32 y1, u32 x2, u32 y2, u32 color);
    void DrawString(const Font& font, const char* string, u32 posX, u32 posY, u32 color);
    void CopyToFrameBuffer(CBcmFrameBuffer& frameBuffer);
private:
    u32* m_BufferPointer{nullptr};
    u32 m_Width{0};
    u32 m_Height{0};
    u32 m_Pitch{0};
    u32 m_Size{0};
};

#endif

HDMIDraw.cpp

#include "HDMIDraw.h"
#include "text.h"
#include <string.h>

MemoryBuffer::MemoryBuffer()
    : m_BufferPointer(nullptr), m_Width(0), m_Height(0), m_Pitch(0), m_Size(0) {
}

MemoryBuffer::~MemoryBuffer() {
    delete[] m_BufferPointer;
}

// Method to allocate the buffer in memory and set fields m_Width, m_Height, and m_Pitch
void MemoryBuffer::Allocate(u32 Width, u32 Height, u32 Pitch) {
    m_Width = Width;
    m_Height = Height;
    m_Pitch = Pitch;
}

我反复检查了字符绘制和像素绘制的逻辑,没发现明显的错误,实在搞不懂为什么只有特定字符、且绘制数量达到32个以上时才会触发这个glitch。有没有大佬能帮我分析下可能的原因,或者给我一些排查的方向?另外我已经附上了故障的效果截图(字符绘制故障效果)。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 03:13:00