threadx之levelx组件的使用记录(结合w25q128)

发布于:2024-04-15 ⋅ 阅读:(183) ⋅ 点赞:(0)

官方概述

在这里插入图片描述

整体代码框架

在这里插入图片描述

代码

核心逻辑部分(tx os对接)

/*
 * Copyright (c) 2024-2024,shchl
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2024-4-4     shchl   first version
 *
 *
 * tx_kernel_enter() 执行逻辑(关键)
 *   TX_PORT_SPECIFIC_PRE_INITIALIZATION----可扩展
 *    _tx_initialize_low_level() --- 设备层(寄存器)初始化
 *    _tx_initialize_high_level() --- tx os 内部相关初始化
 *   TX_INITIALIZE_KERNEL_ENTER_EXTENSION----可扩展
 *     tx_application_define(_tx_initialize_unused_memory);
 *   TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION ---可扩展
 *
 */

#include "includes.h"

#define APP_MAIN_STACK_SIZE 2048
#define APP_MEM_ALLOC_STATIC_ENABLE (0) /*静态内存分配使能*/


/*
*******************************************************************************************************
*                               外部引入变量
*******************************************************************************************************
*/
extern void app_component_init(void);
extern void app_define_component_init(void);
/*
*******************************************************************************************************
*                               变量
*******************************************************************************************************
*/


/*
*********************************************************************************************************
*                                       静态全局变量
*********************************************************************************************************
*/
static TX_THREAD app_start_thread; /*应用启动线程*/
/*
*********************************************************************************************************
*                                      函数声明
*********************************************************************************************************
*/
static void app_start_entry(ULONG input);
/*
*********************************************************************************************************
*                                      内部函数
*********************************************************************************************************
*/

static void app_start_entry(ULONG input) {
    /*应用组件初始化*/
    app_component_init();
    while (1) {
        /* 需要周期性处理的程序,对应裸机工程调用的SysTick_ISR */
        bsp_ProPer1ms();
        tx_thread_sleep(1);
    }
}



/**
  * @brief  应用组件定义初始化
  * @param  first_unused_memory : 指向第一个未使用的内存的指针
  * @retval None
  */
VOID tx_application_define(VOID *first_unused_memory) {
    UINT stat;
#if APP_MEM_ALLOC_STATIC_ENABLE
#define TX_STATIC_MEM_SIZE (60*1024) /*静态内存字节数*/
    /*内存池初始化*/
    static uint8_t mem_pool_area[TX_STATIC_MEM_SIZE];
    tx_mem_pool_static_init(mem_pool_area, TX_STATIC_MEM_SIZE);
#else
    if (first_unused_memory) {
        tx_mem_pool_init(first_unused_memory);
    } else {
        // todo 未使用动态内存,后面禁止使用 app_malloc 函数
        /*错误处理: 线程创建失败*/
        Error_Handler();
    }
#endif
    stat = tx_thread_create(&app_start_thread, "app start thread",
                            app_start_entry, 0,
                            app_malloc(APP_MAIN_STACK_SIZE), APP_MAIN_STACK_SIZE,
                            2, 2,
                            TX_NO_TIME_SLICE, TX_AUTO_START);
    if (stat != TX_SUCCESS) {

        /*错误处理: 线程创建失败*/
        Error_Handler();
    }
    /*组件初始化---不需要主线程中进行初始化的部分,使用TX_APP_DEFINE_EXPORT此进行初始化*/
    app_define_component_init();
}

自动初始化组件

使用到的宏定义

#define TX_APP_DEFINE_EXPORT(fn) INIT_EXPORT(fn, "6.5")
#define TX_THREAD_EXPORT_LV1(fn) INIT_EXPORT(fn, "7.0")
#define TX_THREAD_EXPORT(fn) INIT_EXPORT(fn, "7.5")
/*
 * Copyright (c) 2024-2024,shchl
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2024-4-13     shchl   first version
 */
#include "includes.h"


/*
*******************************************************************************************************
*                               外部引入变量
*******************************************************************************************************
*/

/*
*******************************************************************************************************
*                               变量
*******************************************************************************************************
*/
TX_MUTEX AppPrintfSemp;    /* 用于printf互斥 */

/*
*********************************************************************************************************
*                                       静态全局变量
*********************************************************************************************************
*/
/*
*********************************************************************************************************
*                                      函数声明
*********************************************************************************************************
*/
/**
 * @brief 组件初始化开始
 * @return
 */
static int tx_app_define_init_start() {

    return TX_SUCCESS;
}

INIT_EXPORT(tx_app_define_init_start, "6");

/**
 * @brief 组件初始化开始
 * @return
 */
static int tx_component_init_start() {


    /* 创建互斥信号量 */
    tx_mutex_create(&AppPrintfSemp, "AppPrintfSemp", TX_NO_INHERIT);

    return TX_SUCCESS;
}

INIT_EXPORT(tx_component_init_start, "7");


static int tx_component_init_end() {

    return TX_SUCCESS;
}
INIT_EXPORT(tx_component_init_end, "8");

void app_component_init(void) {
    tx_log("--------------app component init[start]---------------\r\n");
    bsp_components_app_init(&__os_init_tx_component_init_start,
                            &__os_init_tx_component_init_end);
    tx_log("--------------app component init[end]---------------\r\n");

}

void app_define_component_init(void) {
    bsp_components_app_init(&__os_init_tx_app_define_init_start,
                            &__os_init_tx_component_init_start);

}

levelx组件的初始化(这里使用的是自动初始化方式)

/*
 * Copyright (c) 2024-2024,shchl
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2024-4-15     shchl   first version
 */
#include "includes.h"


#if 1

#include "lx_api.h"
#include "levelx/lx_stm32_nor_w25q128_driver.h"

LX_NOR_FLASH nor_w25q128;


int lx_application_define(void) {

    lx_nor_flash_initialize();

    return LX_SUCCESS;
}

TX_APP_DEFINE_EXPORT(lx_application_define); /*首先创建模块应用*/


/**
 * @brief nor flash 设备初始化
 * @return 
 */
int app_nor_flash_init() {
    UINT status = lx_nor_flash_open(&nor_w25q128,
                                    "nor w25q128",
                                    lx_stm32_nor_w25q128bv_driver_initialize);
    /*打开失败(将失败的空间进行格式化)*/
    if (status) { /*这个一般只会执行一次,后面基本上不会再执行*/
        tx_log("need format space\r\n");
        lx_stm32_nor_w25q128bv_flash_format(&nor_w25q128); /*格式化*/
        /*再尝试一次*/
        status = lx_nor_flash_open(&nor_w25q128,
                                   "nor w25q128",
                                   lx_stm32_nor_w25q128bv_driver_initialize);
        if (status) {

            tx_log("nor flash init error\r\n");
            // todo

            return (int) status;
        }


    }

    tx_log("nor flash device init ok\r\n");

    // 是否需要关?
    //lx_nor_flash_close(&nor_w25q128);/*这里直接关闭,后面如果需要,再打开*/
    return (int) LX_SUCCESS; /*返回状态*/
}

TX_THREAD_EXPORT(app_nor_flash_init); 


#endif

levelx驱动实现(w25q128)

头文件

/**************************************************************************/
/*                                                                        */
/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
/*                                                                        */
/*       This software is licensed under the Microsoft Software License   */
/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
/*       and in the root directory of this software.                      */
/*                                                                        */
/**************************************************************************/

#ifndef LX_STM32_NOR_DRIVER_H
#define LX_STM32_NOR_DRIVER_H

#ifdef __cplusplus
extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/
#include "lx_api.h"

#define W25Q128_PHY_TOTAL_SIZE (16*1024*1024)   /*16M*/
#define W25Q128_PHY_PER_BLOCK_SIZE (64*1024)   /*64KB*/
#define W25Q128_PHY_PER_SECTOR_SIZE (4*1024)    /*4KB*/



#define LX_NOR_W25Q128_BASE_ADDR        (0x0U)       /*相对于硬件的基地址*/
#define LX_NOR_W25Q128_ALLOC_TOTAL_SIZE (2*1024*1024) /*分配给LX管理 2M*/
#define LX_NOR_W25Q128_PER_BLOCK_SIZE   W25Q128_PHY_PER_SECTOR_SIZE  /*LX每个块的大小(字节)*/
#define LX_NOR_W25Q128_BLOCKS_NUM     ((LX_NOR_W25Q128_ALLOC_TOTAL_SIZE)/(LX_NOR_W25Q128_PER_BLOCK_SIZE)) /*LX 总块数*/


UINT lx_stm32_nor_w25q128bv_driver_initialize(LX_NOR_FLASH *nor_flash);

UINT lx_stm32_nor_w25q128bv_flash_format(LX_NOR_FLASH *nor_flash);
#ifdef __cplusplus
}
#endif
#endif /* LX_STM32_NOR_DRIVER_H */


源文件

/**************************************************************************/
/*                                                                        */
/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
/*                                                                        */
/*       This software is licensed under the Microsoft Software License   */
/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
/*       and in the root directory of this software.                      */
/*                                                                        */
/**************************************************************************/
#include "includes.h"
#include "levelx/lx_stm32_nor_w25q128_driver.h"

/* Private includes ----------------------------------------------------------*/

/* USER CODE BEGIN Includes */





/* Private typedef -----------------------------------------------------------*/

static UINT lx_nor_driver_read(ULONG *flash_address, ULONG *destination, ULONG words);

static UINT lx_nor_driver_write(ULONG *flash_address, ULONG *source, ULONG words);

static UINT lx_nor_driver_block_erase(ULONG block, ULONG erase_count);

static UINT lx_nor_driver_block_erased_verify(ULONG block);

/* USER CODE BEGIN USER_CODE_SECTION_1 */

/* USER CODE END USER_CODE_SECTION_1 */

#ifndef LX_DIRECT_READ

#ifndef LX_NOR_W25Q128_PER_BLOCK_SIZE
#define LX_NOR_W25Q128_PER_BLOCK_SIZE 512
#endif

static ULONG nor_sector_memory[LX_NOR_W25Q128_PER_BLOCK_SIZE / sizeof(ULONG)];
#endif

UINT lx_stm32_nor_w25q128bv_driver_initialize(LX_NOR_FLASH *nor_flash) {
    UINT ret = LX_SUCCESS;
    nor_flash->lx_nor_flash_total_blocks = LX_NOR_W25Q128_BLOCKS_NUM;
    nor_flash->lx_nor_flash_words_per_block = LX_NOR_W25Q128_PER_BLOCK_SIZE / sizeof(ULONG);
    nor_flash->lx_nor_flash_driver_read = lx_nor_driver_read;
    nor_flash->lx_nor_flash_driver_write = lx_nor_driver_write;

    nor_flash->lx_nor_flash_driver_block_erase = lx_nor_driver_block_erase;
    nor_flash->lx_nor_flash_driver_block_erased_verify = lx_nor_driver_block_erased_verify;

#ifndef LX_DIRECT_READ
    nor_flash->lx_nor_flash_sector_buffer = nor_sector_memory; /*直接赋值底层数据缓冲区,避免多次开辟数据*/
#endif
    return ret;
}

/**
 * @brief
 * @param flash_address 读取地址
 * @param destination 保存数据的位置
 * @param words 读取的数据量
 * @return
 */

static UINT lx_nor_driver_read(ULONG *flash_address, ULONG *destination, ULONG words) {

    uint32_t real_addr = (uint32_t) flash_address + LX_NOR_W25Q128_BASE_ADDR;
    sf_ReadBuffer((uint8_t *) destination,
                  real_addr,
                  words * sizeof(ULONG));

    return LX_SUCCESS;
}

/**
 * @brief
 * @param flash_address 写入地址
 * @param source 要写入的数据
 * @param words 写入的数据大小(字)
 * @return
 */
static UINT lx_nor_driver_write(ULONG *flash_address, ULONG *source, ULONG words) {
    uint32_t real_addr = (uint32_t) flash_address + LX_NOR_W25Q128_BASE_ADDR;
    sf_WriteBuffer((uint8_t *) source,
                   real_addr,
                   words * sizeof(ULONG));
    return LX_SUCCESS;
}

/**
 * @brief
 * @param block 擦除块的下标
 * @param erase_count 擦除的大小(字)
 *  @note 这里已在驱动写入的时候就会覆盖,这里就不做任何处理了
 * @return
 */
static UINT lx_nor_driver_block_erase(ULONG block, ULONG erase_count) {

//    sf_EraseSector(block * FLASH_SIZE_BYTE_PER_SECTOR);
    return LX_SUCCESS;
}

/**
 * @brief 块擦除验证
 * @param block 块的索引下标
 * @return
 */
static UINT lx_nor_driver_block_erased_verify(ULONG block) {


    return LX_SUCCESS;
}

/**
 * @brief 格式化分配的内存空间
 * @param nor_flash
 * @return
 */
UINT lx_stm32_nor_w25q128bv_flash_format(LX_NOR_FLASH *nor_flash) {
    uint32_t erase_addr = 0;
    for (int i = 0; i < nor_flash->lx_nor_flash_total_blocks; ++i) {
        erase_addr = i * LX_NOR_W25Q128_PER_BLOCK_SIZE + LX_NOR_W25Q128_BASE_ADDR;
        sf_EraseSector(erase_addr);
    }
    return LX_SUCCESS;
}

w25q128驱动(这里使用的是:论坛里面驱动代码)

测试线程(使用串口线程)

/*
 * Copyright (c) 2024-2024,shchl
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2024-4-4     shchl   first version
 */
#include "includes.h"

#if 1
#define APP_TASK_SERIAL_MONI_STK_SIZE 2048
#define APP_TASK_SERIAL_MONI_PRIO 10
/*
*******************************************************************************************************
*                               外部引入变量
*******************************************************************************************************
*/
/*
*******************************************************************************************************
*                               变量
*******************************************************************************************************
*/

/*
*********************************************************************************************************
*                                       静态全局变量
*********************************************************************************************************
*/
static TX_THREAD serial_moni_thread;

/*
*********************************************************************************************************
*                                      函数声明
*********************************************************************************************************
*/
static void serial_moni_entry(ULONG input);
/*
*********************************************************************************************************
*                                      外部函数
*********************************************************************************************************
*/
/**
 * @brief cpu 状态任务
 */
int tx_task_serial_monitor_create() {
    tx_thread_create(&serial_moni_thread,              /* 任务控制块地址 */
                     "serial_moni",               /* 任务名 */
                     serial_moni_entry,                  /* 启动任务函数地址 */
                     0,                             /* 传递给任务的参数 */
                     app_malloc(APP_TASK_SERIAL_MONI_STK_SIZE),            /* 堆栈基地址 */
                     APP_TASK_SERIAL_MONI_STK_SIZE,    /* 堆栈空间大小 */
                     APP_TASK_SERIAL_MONI_PRIO,        /* 任务优先级*/
                     APP_TASK_SERIAL_MONI_PRIO,        /* 任务抢占阀值 */
                     TX_NO_TIME_SLICE,               /* 不开启时间片 */
                     TX_AUTO_START);                 /* 创建后立即启动 */

    return TX_SUCCESS;
}

TX_THREAD_EXPORT(tx_task_serial_monitor_create);

/*
*********************************************************************************************************
*                                      内部函数
*********************************************************************************************************
*/
extern void lx_write_data_test();

static void serial_moni_entry(ULONG input) {
    uint8_t cmd;
    while (1) {
        comGetChar(COM1, &cmd);
        switch (cmd) {
      
            case '1': {

                lx_write_data_test();
            }
                break;

            case '2':
                break;

            case '5':
                app_task_info_out();
                break;

            default:
                break;
        }
        cmd = 0;
        tx_thread_sleep(10);
    }

}

#endif

测试代码

/*
 * Copyright (c) 2024-2024,shchl
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2024-4-15     shchl   first version
 */
#include "includes.h"

#if 1

#include "lx_api.h"

extern LX_NOR_FLASH nor_w25q128;
static ULONG wr_data_buf[LX_NOR_SECTOR_SIZE];
static ULONG rd_data_buf[LX_NOR_SECTOR_SIZE];

void lx_write_data_test() {
    static ULONG dat = 0;
    for (int i = 0; i < LX_NOR_SECTOR_SIZE; ++i) {
        wr_data_buf[i] = dat;
        dat++;
    }
    lx_nor_flash_sector_write(&nor_w25q128, 1, wr_data_buf);

    lx_nor_flash_sector_read(&nor_w25q128, 1, rd_data_buf);

    for (int i = 0; i < LX_NOR_SECTOR_SIZE; ++i) {
        if (wr_data_buf[i] != rd_data_buf[i]) {
            tx_log("lx_write_data_test error\r\n");
            return;
        }
    }
    tx_log("lx_write_data_test ok\r\n");

}


#endif

测试结果

在这里插入图片描述

总结

  1. 这里使用lx_nor_flash_open打开设备的时候会出现状态不正确的情况,原因可能是flash中的数据格式问题,需要格式化一次。

网站公告

今日签到

点亮在社区的每一天
去签到