ST77903 QSPI + STM32H743 + RTThread + LVGL

本文介绍了如何在NUCLEO-H743ZI2板上通过驱动指令优化处理1和4个LANE的兼容,并详细展示了QSPI初始化、LCD操作函数及帧缓存管理。着重于LCD驱动的配置和STM32平台上的内存优化,以解决UI资源放置问题。

因为之前的H750内部空间太小,无法放入UI资源,所以这次直接买了块NUCLEO-H743ZI2,驱动上做了指令1LANE和4LANE的兼容

驱动文件如下:


#include "board.h"
#include "sram.h"
#include "rtthread.h"
#include "rtdevice.h"
#include "lcdqspi.h"


#define DBG
#define DBG_TAG             "lcdqspi"
#include "log.h"

#define FRAME_BLANKING_TIME (10U)
#define FRAME_MEM_SIZE      (LCD_HBYTE * LCD_Y_SIZE)
#define FRAME_MEM_BASE      SRAM_AXI_BASE

#define QSPI_CLK_MHZ        (25)

#if (FRAME_MEM_SIZE > SRAM_AXI_SIZE)
#error "lcdqspi frame cache size is not enough!"
#endif

static uint8_t frame_cache[LCD_Y_SIZE][LCD_HBYTE] __attribute__ ((at(FRAME_MEM_BASE)));
 

void rt_hw_us_delay(rt_uint32_t us);

static QSPI_HandleTypeDef QSPI_Handler; 
static QSPI_CommandTypeDef QSPI_Cmdhandler;

static struct rt_semaphore  trans_sem  = {
   
   0};
static struct rt_completion frame_sync = {
   
   0};
static struct rt_timer      te_timer   = {
   
   0};

static __IO uint32_t te_offset = LCD_TE_OFT;

void QUADSPI_IRQHandler(void)
{
   
   
    IRQ_ENTER();
    HAL_QSPI_IRQHandler(&QSPI_Handler);
    IRQ_LEAVE();
}

void MDMA_IRQHandler(void)
{
   
    
    IRQ_ENTER();
    HAL_MDMA_IRQHandler(QSPI_Handler.hmdma);
    IRQ_LEAVE();
}

void HAL_QSPI_CmdCpltCallback(QSPI_HandleTypeDef *hqspi)
{
   
   
    rt_sem_release(&trans_sem);
}

void HAL_QSPI_TxCpltCallback(QSPI_HandleTypeDef *hqspi)
{
   
   
    rt_sem_release(&trans_sem);
}

void HAL_QSPI_MspInit(QSPI_HandleTypeDef *hqspi)
{
   
   
    static MDMA_HandleTypeDef hmdma;

    __HAL_RCC_QSPI_CLK_ENABLE();
    __HAL_RCC_QSPI_FORCE_RESET();
    __HAL_RCC_QSPI_RELEASE_RESET();

    __HAL_RCC_MDMA_CLK_ENABLE();
    __HAL_RCC_MDMA_FORCE_RESET();
    __HAL_RCC_MDMA_RELEASE_RESET();

    HAL_NVIC_SetPriority(QUADSPI_IRQn, NVIC_PRIORITY_QSPI, 0);
    HAL_NVIC_EnableIRQ(QUADSPI_IRQn);

    hmdma.Init.Request              = MDMA_REQUEST_QUADSPI_FIFO_TH;
    hmdma.Init.TransferTriggerMode  = MDMA_BUFFER_TRANSFER;
    hmdma.Init.Priority             = MDMA_PRIORITY_HIGH;
    hmdma.Init.Endianness           = MDMA_LITTLE_ENDIANNESS_PRESERVE;

    hmdma.Init.SourceInc            = MDMA_SRC_INC_BYTE;
    hmdma.Init.DestinationInc       = MDMA_DEST_INC_DISABLE;
    hmdma.Init.SourceDataSize       = MDMA_SRC_DATASIZE_BYTE;
    hmdma.Init.DestDataSize         = MDMA_DEST_DATASIZE_BYTE;
    hmdma.Init.DataAlignment        = MDMA_DATAALIGN_PACKENABLE;
    hmdma.Init.BufferTransferLength = 16;
    hmdma.Init.SourceBurst          = MDMA_SOURCE_BURST_SINGLE;
    hmdma.Init.DestBurst            = MDMA_DEST_BURST_SINGLE;

    hmdma.Init.SourceBlockAddressOffset = 0;
    hmdma.Init.DestBlockAddressOffset   = 0;

    hmdma.Instance = MDMA_Channel1;

    __HAL_LINKDMA(hqspi, hmdma, hmdma);
    HAL_MDMA_DeInit(&hmdma);      
    HAL_MDMA_Init(&hmdma);
    HAL_NVIC_SetPriority(MDMA_IRQn, 0x00, 0);
    HAL_NVIC_EnableIRQ(MDMA_IRQn);  
}

void HAL_QSPI_MspDeInit(QSPI_HandleTypeDef *hqspi)
{
   
   
    __HAL_RCC_QSPI_FORCE_RESET();
    __HAL_RCC_QSPI_RELEASE_RESET();
    HAL_NVIC_DisableIRQ(QUADSPI_IRQn);

    __HAL_RCC_MDMA_FORCE_RESET();
    __HAL_RCC_MDMA_RELEASE_RESET();
    HAL_NVIC_DisableIRQ(MDMA_IRQn);
} 


/* QSPI initialize */
static void ll_qspi_init(void)
{
   
   
    static DMA_HandleTypeDef hdma;

    __HAL_RCC_QSPI_CLK_ENABLE();        

    __HAL_RCC_DMA1_CLK_ENABLE();  
    
    QSPI_Handler.Instance                = QUADSPI;     

    /* D1HCLK(200MHz) / (prescaler + 1) = 200/5 = 40MHZ */
    QSPI_Handler.Init.ClockPrescaler     = 200 / QSPI_CLK_MHZ - 1;                                                                   
    QSPI_Handler.Init.FifoThreshold      = 16;                     
    QSPI_Handler.Init.SampleShifting     = QSPI_SAMPLE_SHIFTING_NONE;
    QSPI_Handler.Init.FlashSize          = POSITION_VAL(0X800000)-1;  
    QSPI_Handler.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_5_CYCLE;
    
    /* clock keep high level in idle time cs inactive */
    QSPI_Handler.Init.ClockMode          = QSPI_CLOCK_MODE_3;        
    QSPI_Handler.Init.FlashID            = QSPI_FLASH_ID_1;              
    QSPI_Handler.Init.DualFlash          = QSPI_DUALFLASH_DISABLE;     
    HAL_QSPI_Init(&QSPI_Handler);

    /* 0xde is the first byte every transmit */
    QSPI_Cmdhandler.Instruction     = 0xde;
    /* qspi 24bit address, lcd command is set in A15~A8 */
    QSPI_Cmdhandler.Address         = 0x000000;
    QSPI_Cmdhandler.DummyCycles     = 0;
    QSPI_Cmdhandler.InstructionMode = QSPI_INSTRUCTION_1_LINE;
    QSPI_Cmdhandler.AddressMode     = QSPI_ADDRESS_1_LINE;
    QSPI_Cmdhandler.AddressSize     = QSPI_ADDRESS_24_BITS;    
    QSPI_Cmdhandler.DataMode        = QSPI_DATA_NONE;    
    QSPI_Cmdhandler.NbData          = 0;

    QSPI_Cmdhandler.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;               
    QSPI_Cmdhandler.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;   
    QSPI_Cmdhandler.DdrMode           = QSPI_DDR_MODE_DISABLE;                  
    QSPI_Cmdhandler.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
}

/* lcd delay millisecond */
__INLINE static void lcd_dlyms(uint32_t ms)
{
   
   
    rt_thread_delay(ms);
}

__INLINE static void lcd_dlyus(uint32_t us)
{
   
   
    rt_hw_us_delay(us);
}

/* lcd transmit, write command, write display data */
static void lcd_transmit(uint32_t cmd, uint32_t len, uint8_t *dat)
{
   
   
    if (len == 0)              
    {
   
                              /* write command, no parameter */
#if (CMD_LANE == CMD_LANE_1)
        QSPI_Cmdhandler.Instruction     = 0xd8;
        QSPI_Cmdhandler.InstructionMode = QSPI_INSTRUCTION_1_LINE;     
        QSPI_Cmdhandler.AddressMode     = QSPI_ADDRESS_1_LINE;  
        QSPI_Cmdhandler.DataMode        = QSPI_DATA_NONE;    
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值