本帖最后由 walker2048 于 2023-4-2 20:13 编辑
三、适配腾讯TinyOS的vfs和fatfs组件
1. 由于第一次使用单片机实现SD卡读取,对这方面并不熟悉,所以我只能先使用国民技术官方SDIO的demo来学习。通过demo源码的阅读,可以看出该源码支持SDIO 1bit,4bit,8bit模式(8bit模式应该是适配emmc的)。然后我手上的SD卡模块是spi方式接入,通过对比spi模式和SDIO 1bit模式的引脚,可以使用。以下是接线图。
通过修改源码里传递给SD_Init()函数的第三个参数(由原来的4改为1),即可运行该demo,并对SD卡进行读写测试。测试内容如下。
demo正确获取到了SD卡的信息(除容量获取错误以外),也正确写入和读出了扇区的内容。可以开始移植了。
2. 处理原sdio源码文件
可能是出于兼容性的考虑,腾讯TinyOS的sd卡初始化函数是不传递任何参数的,所以我们需要将原sdio实现代码中的SD_Init函数更名为__SD_Init,并在文件尾重写一个SD_Init函数。以下为改写内容。
SD_Error SD_Init(){
return __SD_Init(0, 3, 1);
}
3. 实现tos_hal_sd的接口函数
腾讯TinyOS的Fatfs组件里会调用tos_hal_sd层级的函数,避免直接调用芯片级的hal函数,实现多种芯片的软件兼容。所以我们需要为国民N32G457编写对应的文件。
hardware/chip/nationstech/tos_hal/tos_hal_sd.c(文件路径)
#include "tos_k.h"
#include "tos_hal.h"
#include "sdio_tf.h"
__API__ int tos_hal_sd_init(hal_sd_t *sd)
{
(void)sd;
return SD_Init() == SD_OK ? 0 : -1;
}
__API__ int tos_hal_sd_read(hal_sd_t *sd, uint8_t *buf, uint32_t blk_addr, uint32_t blk_num, uint32_t timeout)
{
uint8_t err;
(void)sd;
if (!buf) {
return -1;
}
err = SD_ReadDisk(buf, blk_addr, blk_num);
err = SD_WaitWriteOperation();
return err == SD_OK ? 0 : -1;
}
__API__ int tos_hal_sd_write(hal_sd_t *sd, const uint8_t *buf, uint32_t blk_addr, uint32_t blk_num, uint32_t timeout)
{
uint8_t err;
(void)sd;
if (!buf) {
return -1;
}
err = SD_WriteDisk((uint8_t *)buf, blk_addr, blk_num);
err = SD_WaitWriteOperation();
return err == SD_OK ? 0 : -1;
}
__API__ int tos_hal_sd_read_dma(hal_sd_t *sd, uint8_t *buf, uint32_t blk_addr, uint32_t blk_num)
{
return -1;
}
__API__ int tos_hal_sd_write_dma(hal_sd_t *sd, const uint8_t *buf, uint32_t blk_addr, uint32_t blk_num)
{
return -1;
}
__API__ int tos_hal_sd_erase(hal_sd_t *sd, uint32_t blk_add_start, uint32_t blk_addr_end)
{
return 0;
}
__API__ int tos_hal_sd_info_get(hal_sd_t *sd, hal_sd_info_t *info)
{
SD_Error err;
SD_CardInfo card_info;
(void)sd;
if (!sd || !info) {
return -1;
}
err = SD_GetCardInfo(&card_info);
if (err != SD_OK) {
return -1;
}
info->card_type = card_info.CardType;
info->blk_num = card_info.CardCapacity / card_info.CardBlockSize;
info->blk_size = card_info.CardBlockSize;
return 0;
}
__API__ int tos_hal_sd_state_get(hal_sd_t *sd, hal_sd_state_t *state)
{
int ret = 0;
SDCardState sd_state;
(void)sd;
if (!sd || !state) {
return -1;
}
sd_state = SD_GetState();
switch (sd_state) {
case SD_CARD_READY:
*state = HAL_SD_STAT_READY;
break;
case SD_CARD_SENDING:
*state = HAL_SD_STAT_PROGRAMMING;
break;
case SD_CARD_RECEIVING:
*state = HAL_SD_STAT_RECEIVING;
break;
case SD_CARD_TRANSFER:
*state = HAL_SD_STAT_TRANSFER;
break;
case SD_CARD_ERROR:
*state = HAL_SD_STAT_ERROR;
break;
default:
ret = -1;
break;
}
return ret;
}
__API__ int tos_hal_sd_deinit(hal_sd_t *sd)
{
(void)sd;
return 0;
}
4. 将对应文件添加到GN构建配置文件中
添加了新的c源文件,我们需要把对应的文件添加到GN构建配置文件中,每个组件的根目录下都有一个BUILD.gn配置文件。该文件定义了组件包含的文件,组件编译选项(若需要添加),组件依赖等等内容。
由于腾讯TinyOS并没有实现完整的系统级hal层函数,这个tos_hal_sd.c文件就暂时放在厂商芯片代码目录中(hardware/chip/nationstech/),我们在配置文件的最后添加这个文件的配置。
source_set("n32g457_sdk") {
sources = [
"Peripheral/misc.c",
"Peripheral/n32g45x_adc.c",
"Peripheral/n32g45x_bkp.c",
"Peripheral/n32g45x_can.c",
"Peripheral/n32g45x_comp.c",
"Peripheral/n32g45x_crc.c",
"Peripheral/n32g45x_dbg.c",
"Peripheral/n32g45x_dma.c",
"Peripheral/n32g45x_dvp.c",
"Peripheral/n32g45x_eth.c",
"Peripheral/n32g45x_exti.c",
"Peripheral/n32g45x_flash.c",
"Peripheral/n32g45x_gpio.c",
"Peripheral/n32g45x_i2c.c",
"Peripheral/n32g45x_iwdg.c",
"Peripheral/n32g45x_opamp.c",
"Peripheral/n32g45x_pwr.c",
"Peripheral/n32g45x_qspi.c",
"Peripheral/n32g45x_rcc.c",
"Peripheral/n32g45x_rtc.c",
"Peripheral/n32g45x_sdio.c",
"Peripheral/n32g45x_spi.c",
"Peripheral/n32g45x_tim.c",
"Peripheral/n32g45x_usart.c",
"Peripheral/n32g45x_wwdg.c",
]
sources += [
"USBFS/usb_core.c",
"USBFS/usb_init.c",
"USBFS/usb_int.c",
"USBFS/usb_mem.c",
"USBFS/usb_regs.c",
"USBFS/usb_sil.c",
]
sources += [
"sdio_tf.c",
"system_n32g45x.c",
]
sources += [ "../tos_hal/tos_hal_sd.c" ]
}
适配完毕后,编译源码,默认配置下,TinyOS的fatfs还是比较大的体积的。通过psize命令,可以看到fs/fatfs组件体积又182.3K这么大,如此大的体积,是不符合BootLoader的需求的。
5. 检查代码是否可以读写tf卡
通过修改hardware/board/n32g45xvl_STB/main.c文件,我们尝试初始化SD卡和擦写部分扇区(直接调用SD_WriteBlock函数)
/*****************************************************************************
* Copyright (c) 2019, Nations Technologies Inc.
*
* All rights reserved.
* ****************************************************************************
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Nations' name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ****************************************************************************/
/**
* [url=home.php?mod=space&uid=288409]@file[/url] main.c
* [url=home.php?mod=space&uid=187600]@author[/url] Nations
* [url=home.php?mod=space&uid=895143]@version[/url] v1.0.0
*
* [url=home.php?mod=space&uid=17282]@CopyRight[/url] Copyright (c) 2019, Nations Technologies Inc. All rights reserved.
*/
#include "main.h"
#include "n32g45x.h"
#include "sdio_tf.h"
#include "stdint.h"
#include "stdio.h"
#include "tos_k.h"
#define USARTx USART1
#define USARTx_GPIO GPIOA
#define USARTx_CLK RCC_APB2_PERIPH_USART1
#define USARTx_GPIO_CLK RCC_APB2_PERIPH_GPIOA
#define USARTx_RxPin GPIO_PIN_10
#define USARTx_TxPin GPIO_PIN_9
#define GPIO_APBxClkCmd RCC_EnableAPB2PeriphClk
#define USART_APBxClkCmd RCC_EnableAPB2PeriphClk
#ifdef __GNUC__
/* With GCC, small printf (option LD Linker->Libraries->Small printf
set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(char ch)
#define GETCHAR_PROTOTYPE int __io_getchar()
#else
#define PUTCHAR_PROTOTYPE int fputc(char ch)
#define GETCHAR_PROTOTYPE int fgetc()
#endif /* __GNUC__ */
PUTCHAR_PROTOTYPE {
if (ch == '\n') {
while (USART_GetFlagStatus(USARTx, USART_FLAG_TXC) == RESET)
;
USART_SendData(USARTx, '\r');
}
while (USART_GetFlagStatus(USARTx, USART_FLAG_TXC) == RESET)
;
USART_SendData(USARTx, ch);
return ch;
}
GETCHAR_PROTOTYPE {
uint8_t ch = 0;
ch = USART_ReceiveData(USARTx);
return ch;
}
/** @addtogroup N32G45X_StdPeriph_Examples
* @{
*/
/** @addtogroup USART_Printf
* @{
*/
typedef enum { FAILED = 0, PASSED = !FAILED } TestStatus;
#define countof(a) (sizeof(a) / sizeof(*(a)))
USART_InitType USART_InitStructure;
void RCC_Configuration(void);
#define APPLICATION_TASK_STK_SIZE 1024
k_task_t application_task;
__aligned(4) uint8_t application_task_stk[APPLICATION_TASK_STK_SIZE];
u8 buf[512];
u8 Readbuf[512];
/*********************************************************************
* @fn show_sdcard_info
*
* [url=home.php?mod=space&uid=247401]@brief[/url] SD Card information.
*
* [url=home.php?mod=space&uid=266161]@return[/url] none
*/
void show_sdcard_info(void) {
printf("SD Card initialization success!\r\n");
printf("*CardType is: %d\r\n", SDCardInfo.CardType);
printf("*CardCapacity is: %lld\r\n",
SDCardInfo.CardCapacity / (1024 * 1024));
printf("*CardBlockSize is: %d\r\n", (int)SDCardInfo.CardBlockSize);
printf("*RCA is: %d\r\n", SDCardInfo.RCA);
printf("*Manufacture(MID) is: %d\r\n", SDCardInfo.SD_cid.ManufacturerID);
printf("*OEM/Appli(OID) is: %d\r\n", SDCardInfo.SD_cid.OEM_AppliID);
printf("*Product Name(PNM) is: %d\r\n", (int)SDCardInfo.SD_cid.ProdName1);
printf("*Serial Number(PSN) is: %x\r\n",
(unsigned int)SDCardInfo.SD_cid.ProdSN);
printf("*Manu Date COde(MDT) is: %x\r\n", SDCardInfo.SD_cid.ManufactDate);
printf("*Card SysSpecVersion is: %d\r\n", SDCardInfo.SD_csd.SysSpecVersion);
printf("*Card MaxBusClkFrec is: %d\r\n", SDCardInfo.SD_csd.MaxBusClkFrec);
printf("*Card MaxRdBlockLen is: %d\r\n", SDCardInfo.SD_csd.RdBlockLen);
printf("*Card RdCurrent VDD is: %d -> %d\r\n",
SDCardInfo.SD_csd.MaxRdCurrentVDDMin,
SDCardInfo.SD_csd.MaxRdCurrentVDDMax);
printf("*Card WrSpeedFact is: %d\r\n", SDCardInfo.SD_csd.WrSpeedFact);
printf("*Card MaxWrBlockLen is: %d\r\n", SDCardInfo.SD_csd.MaxWrBlockLen);
printf("*Card WrCurrent VDD is: %d -> %d\r\n",
SDCardInfo.SD_csd.MaxWrCurrentVDDMin,
SDCardInfo.SD_csd.MaxWrCurrentVDDMax);
}
SD_Error Status = SD_OK;
void application_entry(void *arg) {
u32 i;
u32 Sector_Nums;
while (SD_Init()) {
printf("SD Card Error!\r\n");
tos_task_delay(1000);
}
show_sdcard_info();
printf("SD Card OK\r\n");
Sector_Nums = ((u32)(SDCardInfo.CardCapacity >> 20)) / 2;
printf("Sector_Nums:%d\r\n", Sector_Nums);
for (i = 0; i < 512; i++) {
buf[i] = i;
}
for (i = 0; i < 512; i++) {
Status = SD_WriteBlock(buf, i, 1);
Status = SD_WaitWriteOperation();
while (SD_GetStatus() != SD_TRANSFER_OK)
;
if (Status != SD_OK) {
printf("SD Card write block failed!\r\n");
}
Status = SD_ReadBlock(Readbuf, i, 1);
Status = SD_WaitReadOperation();
while (SD_GetStatus() != SD_TRANSFER_OK)
;
if (memcmp(buf, Readbuf, 512)) {
printf(" %d sector Verify fail\n", i);
break;
}
}
if (i == Sector_Nums / 2) {
printf("SD OK\r\n");
}
}
/**
* @brief Main program
*/
int main(void) {
/* System Clocks Configuration */
RCC_Configuration();
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
/* Configure the GPIO ports */
GPIO_InitType GPIO_InitStructure;
/* Configure USARTx Tx as alternate function push-pull */
GPIO_InitStructure.Pin = USARTx_TxPin;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitPeripheral(USARTx_GPIO, &GPIO_InitStructure);
/* Configure USARTx Rx as input floating */
GPIO_InitStructure.Pin = USARTx_RxPin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitPeripheral(USARTx_GPIO, &GPIO_InitStructure);
/* USARTy and USARTz configuration
* ------------------------------------------------------*/
USART_InitStructure.BaudRate = 115200;
USART_InitStructure.WordLength = USART_WL_8B;
USART_InitStructure.StopBits = USART_STPB_1;
USART_InitStructure.Parity = USART_PE_NO;
USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
USART_InitStructure.Mode = USART_MODE_RX | USART_MODE_TX;
/* Configure USARTx */
USART_Init(USARTx, &USART_InitStructure);
/* Enable the USARTx */
USART_Enable(USARTx, ENABLE);
tos_knl_init(); // 初始化TencentOS tiny内核
printf("TinyOS demo!\r\n");
// 创建一个优先级为5的任务
tos_task_create(&application_task, "task_prio5", application_entry, NULL, 4,
application_task_stk, APPLICATION_TASK_STK_SIZE, 0);
// 开始内核调度,线程中不允许有睡死代码。
tos_knl_start();
while (1) {
}
}
/**
* @brief Configures the different system clocks.
*/
void RCC_Configuration(void) {
/* Enable GPIO clock */
GPIO_APBxClkCmd(USARTx_GPIO_CLK | RCC_APB2_PERIPH_AFIO, ENABLE);
/* Enable USARTy and USARTz Clock */
USART_APBxClkCmd(USARTx_CLK, ENABLE);
}
烧录到开发板上,可以正确获取SD卡信息,并读写SD卡扇区。SDIO代码没问题。
四、fatfs编译优化注意事项
1. 回到上一个步骤的fatfs体积的问题,通过搜索引擎可以查到,我们可以调整FF_USE_LFN 宏定义的值,关闭长文件名的支持。以下为修改后的代码。
文件路径 components/fs/fatfs/wrapper/include/tos_ffconf.h (由于腾讯TinyOS改写了fatfs的源码,并重命名了ffconf.h文件,我们需要修改这个文件才能生效)。
#define FF_USE_LFN 0
#define FF_MAX_LFN 255
/* The FF_USE_LFN switches the support for LFN (long file name).
/
/ 0: Disable LFN. FF_MAX_LFN has no effect.
/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe.
/ 2: Enable LFN with dynamic working buffer on the STACK.
/ 3: Enable LFN with dynamic working buffer on the HEAP.
/
/ To enable the LFN, ffunicode.c needs to be added to the project. The LFN function
/ requiers certain internal working buffer occupies (FF_MAX_LFN + 1) * 2 bytes and
/ additional (FF_MAX_LFN + 44) / 15 * 32 bytes when exFAT is enabled.
/ The FF_MAX_LFN defines size of the working buffer in UTF-16 code unit and it can
/ be in range of 12 to 255. It is recommended to be set 255 to fully support LFN
/ specification.
/ When use stack for the working buffer, take care on stack overflow. When use heap
/ memory for the working buffer, memory management functions, ff_memalloc() and
/ ff_memfree() in ffsystem.c, need to be added to the project. */
执行mclean命令清空了编译产物后,重新执行mbuild和psize命令,可以看到fatfs的组件体积减小到了8.9K,体积减小了不少。
虽然整体体积34K的flash,对于16K的目标BootLoader大小来说还是相差比较大。目前就暂时不管他,先考虑完成IAP功能(SDIO功能占用体积极大,估计要换成SPI或者软SPI读写SD卡能降低不少体积)。
这里我们用TinyOS的VFS层代码进行测试,测试代码如下(同样是修改上文提到的main.c文件):
/*****************************************************************************
* Copyright (c) 2019, Nations Technologies Inc.
*
* All rights reserved.
* ****************************************************************************
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Nations' name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ****************************************************************************/
/**
* @file main.c
* @author Nations
* @version v1.0.0
*
* @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved.
*/
#include "main.h"
#include "n32g45x.h"
#include "sdio_tf.h"
#include "stdint.h"
#include "stdio.h"
#include "tos_k.h"
#define USARTx USART1
#define USARTx_GPIO GPIOA
#define USARTx_CLK RCC_APB2_PERIPH_USART1
#define USARTx_GPIO_CLK RCC_APB2_PERIPH_GPIOA
#define USARTx_RxPin GPIO_PIN_10
#define USARTx_TxPin GPIO_PIN_9
#define GPIO_APBxClkCmd RCC_EnableAPB2PeriphClk
#define USART_APBxClkCmd RCC_EnableAPB2PeriphClk
#ifdef __GNUC__
/* With GCC, small printf (option LD Linker->Libraries->Small printf
set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(char ch)
#define GETCHAR_PROTOTYPE int __io_getchar()
#else
#define PUTCHAR_PROTOTYPE int fputc(char ch)
#define GETCHAR_PROTOTYPE int fgetc()
#endif /* __GNUC__ */
PUTCHAR_PROTOTYPE {
if (ch == '\n') {
while (USART_GetFlagStatus(USARTx, USART_FLAG_TXC) == RESET)
;
USART_SendData(USARTx, '\r');
}
while (USART_GetFlagStatus(USARTx, USART_FLAG_TXC) == RESET)
;
USART_SendData(USARTx, ch);
return ch;
}
GETCHAR_PROTOTYPE {
uint8_t ch = 0;
ch = USART_ReceiveData(USARTx);
return ch;
}
/** @addtogroup N32G45X_StdPeriph_Examples
* @{
*/
/** @addtogroup USART_Printf
* @{
*/
typedef enum { FAILED = 0, PASSED = !FAILED } TestStatus;
#define countof(a) (sizeof(a) / sizeof(*(a)))
USART_InitType USART_InitStructure;
void RCC_Configuration(void);
#define APPLICATION_TASK_STK_SIZE 1024
k_task_t application_task;
__aligned(4) uint8_t application_task_stk[APPLICATION_TASK_STK_SIZE];
/*********************************************************************
* @fn show_sdcard_info
*
* @brief SD Card information.
*
* @return none
*/
void show_sdcard_info(void) {
printf("SD Card initialization success!\r\n");
printf("*CardType is: %d\r\n", SDCardInfo.CardType);
printf("*CardCapacity is: %lld\r\n",
SDCardInfo.CardCapacity / (1024 * 1024));
printf("*CardBlockSize is: %d\r\n", (int)SDCardInfo.CardBlockSize);
printf("*RCA is: %d\r\n", SDCardInfo.RCA);
printf("*Manufacture(MID) is: %d\r\n", SDCardInfo.SD_cid.ManufacturerID);
printf("*OEM/Appli(OID) is: %d\r\n", SDCardInfo.SD_cid.OEM_AppliID);
printf("*Product Name(PNM) is: %d\r\n", (int)SDCardInfo.SD_cid.ProdName1);
printf("*Serial Number(PSN) is: %x\r\n",
(unsigned int)SDCardInfo.SD_cid.ProdSN);
printf("*Manu Date COde(MDT) is: %x\r\n", SDCardInfo.SD_cid.ManufactDate);
printf("*Card SysSpecVersion is: %d\r\n", SDCardInfo.SD_csd.SysSpecVersion);
printf("*Card MaxBusClkFrec is: %d\r\n", SDCardInfo.SD_csd.MaxBusClkFrec);
printf("*Card MaxRdBlockLen is: %d\r\n", SDCardInfo.SD_csd.RdBlockLen);
printf("*Card RdCurrent VDD is: %d -> %d\r\n",
SDCardInfo.SD_csd.MaxRdCurrentVDDMin,
SDCardInfo.SD_csd.MaxRdCurrentVDDMax);
printf("*Card WrSpeedFact is: %d\r\n", SDCardInfo.SD_csd.WrSpeedFact);
printf("*Card MaxWrBlockLen is: %d\r\n", SDCardInfo.SD_csd.MaxWrBlockLen);
printf("*Card WrCurrent VDD is: %d -> %d\r\n",
SDCardInfo.SD_csd.MaxWrCurrentVDDMin,
SDCardInfo.SD_csd.MaxWrCurrentVDDMax);
}
SD_Error Status = SD_OK;
#include "ff.h"
#include "tos_vfs.h"
#include "tos_fatfs_drv.h"
#include "tos_fatfs_vfs.h"
char buf[512];
void application_entry(void *arg) {
int fd, ret;
vfs_err_t err;
extern vfs_blkdev_ops_t sd_dev;
extern vfs_fs_ops_t fatfs_ops;
err = tos_vfs_block_device_register("/dev/sd", &sd_dev);
if (err != VFS_ERR_NONE) {
printf("/dev/sd block device register failed!\n");
}
err = tos_vfs_fs_register("fatfs_sd", &fatfs_ops);
if (err != VFS_ERR_NONE) {
printf("fatfs_sd fs register failed!\n");
}
if (tos_vfs_fs_mkfs("/dev/sd", "fatfs_sd", FM_FAT32, 0) != 0) {
printf("mkfs failed!\n");
}
if (tos_vfs_fs_mount("/dev/sd", "/fs/fatfs_sd", "fatfs_sd") != 0) {
printf("mount failed!\n");
}
fd = tos_vfs_open("/fs/fatfs_sd/test_file.txt", VFS_OFLAG_CREATE_ALWAYS | VFS_OFLAG_WRITE);
if (fd < 0) {
printf("open failed!\n");
}
ret = tos_vfs_write(fd, "fatfs sample content", strlen("fatfs sample content"));
if (ret >= 0) {
printf("write ok\n");
printf("write data:\n%s\n", "fatfs sample content");
} else {
printf("write error: %d\n", ret);
}
ret = tos_vfs_close(fd);
if (ret < 0) {
printf("close failed!\n");
}
fd = tos_vfs_open("/fs/fatfs_sd/test_file.txt", VFS_OFLAG_EXISTING | VFS_OFLAG_READ);
if (fd < 0) {
printf("open file error!\n");
}
memset(buf, 0, sizeof(buf));
ret = tos_vfs_read(fd, buf, sizeof(buf));
if (ret >= 0) {
printf("read ok: %d\n", ret);
printf("read data:\n%s\n", buf);
} else {
printf("read error: %d\n", ret);
}
////////////////////////////////////////////////
ret = tos_vfs_lseek(fd, 2, VFS_SEEK_CUR);
if (ret < 0) {
printf("lseek error\n");
}
memset(buf, 0, sizeof(buf));
ret = tos_vfs_read(fd, buf, sizeof(buf));
if (ret >= 0) {
printf("read ok: %d\n", ret);
printf("read data:\n%s\n", buf);
} else {
printf("read error: %d\n", ret);
}
/////////////////////////////////////////////////
tos_vfs_close(fd);
}
/**
* @brief Main program
*/
int main(void) {
/* System Clocks Configuration */
RCC_Configuration();
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
/* Configure the GPIO ports */
GPIO_InitType GPIO_InitStructure;
/* Configure USARTx Tx as alternate function push-pull */
GPIO_InitStructure.Pin = USARTx_TxPin;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitPeripheral(USARTx_GPIO, &GPIO_InitStructure);
/* Configure USARTx Rx as input floating */
GPIO_InitStructure.Pin = USARTx_RxPin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitPeripheral(USARTx_GPIO, &GPIO_InitStructure);
/* USARTy and USARTz configuration
* ------------------------------------------------------*/
USART_InitStructure.BaudRate = 115200;
USART_InitStructure.WordLength = USART_WL_8B;
USART_InitStructure.StopBits = USART_STPB_1;
USART_InitStructure.Parity = USART_PE_NO;
USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
USART_InitStructure.Mode = USART_MODE_RX | USART_MODE_TX;
/* Configure USARTx */
USART_Init(USARTx, &USART_InitStructure);
/* Enable the USARTx */
USART_Enable(USARTx, ENABLE);
tos_knl_init(); // 初始化TencentOS tiny内核
printf("TinyOS demo!\r\n");
// 创建一个优先级为5的任务
tos_task_create(&application_task, "task_prio5", application_entry, NULL, 4,
application_task_stk, APPLICATION_TASK_STK_SIZE, 0);
// 开始内核调度,线程中不允许有睡死代码。
tos_knl_start();
while (1) {
}
}
/**
* @brief Configures the different system clocks.
*/
void RCC_Configuration(void) {
/* Enable GPIO clock */
GPIO_APBxClkCmd(USARTx_GPIO_CLK | RCC_APB2_PERIPH_AFIO, ENABLE);
/* Enable USARTy and USARTz Clock */
USART_APBxClkCmd(USARTx_CLK, ENABLE);
}
编译代码后,烧录到板子上测试结果如下:
经过调试和阅读相关源码,暂时未找到为何设备注册错误。阅读原厂SDIO源码发现默认是启用了SDIO的DMA模式(似乎也可以通过宏定义不开启DMA模式,禁用后仍是出现上图的报错),但是由于时间仓储,未能继续再往下开发下去。
总结:通过本次活动,我学习到了N32G457的SDIO读写SD卡,以及腾讯TinyOS的相关移植知识。由于本人的能力不足,未能实现本次活动的目标,但也让我学到了不少知识。由于活动时间结束了,本次的分享只能分享部分经验,而不是完整的IAP功能,只能在4月抽空再完成对应功能,并在本帖跟进对应内容。本次活动的相关源码在https://gitee.com/walker2048/mcu_playground/tree/dev/可以获取到。
|