mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2025-11-16 12:34:33 +00:00
Compare commits
2 Commits
copilot/up
...
copilot/re
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
35e4335ee7 | ||
|
|
6d2f401e17 |
@@ -28,6 +28,5 @@ extern int __bss_end;
|
||||
#define HEAP_END (void*)(0x20000000 + 0xA0000)
|
||||
|
||||
void rt_hw_board_init(void);
|
||||
int rt_vbus_do_init(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -18,10 +18,6 @@
|
||||
#include <shell.h>
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_VBUS
|
||||
#include <vbus.h>
|
||||
#endif
|
||||
|
||||
/* thread phase init */
|
||||
void rt_init_thread_entry(void *parameter)
|
||||
{
|
||||
@@ -32,10 +28,6 @@ void rt_init_thread_entry(void *parameter)
|
||||
finsh_set_device(RT_CONSOLE_DEVICE_NAME);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_VBUS
|
||||
rt_vbus_do_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*the led thread*/
|
||||
@@ -45,8 +37,6 @@ static struct rt_thread led_thread;
|
||||
static void led_thread_entry(void *parameter)
|
||||
{
|
||||
rt_device_t led_dev;
|
||||
rt_device_t vbus_dev;
|
||||
rt_err_t err;
|
||||
|
||||
rt_led_hw_init();
|
||||
|
||||
@@ -57,32 +47,14 @@ static void led_thread_entry(void *parameter)
|
||||
return;
|
||||
}
|
||||
|
||||
vbus_dev = rt_device_find("vecho");
|
||||
if (vbus_dev == RT_NULL)
|
||||
{
|
||||
rt_kprintf("can not find the vbus device\n");
|
||||
return;
|
||||
}
|
||||
|
||||
err = rt_device_open(vbus_dev, RT_DEVICE_OFLAG_RDWR);
|
||||
if (err != RT_EOK)
|
||||
{
|
||||
rt_kprintf("open vbus failed: %d\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
rt_uint8_t led_value;
|
||||
int len;
|
||||
|
||||
len = rt_device_read(vbus_dev, 0, &led_value, sizeof(led_value));
|
||||
if (len <= 0)
|
||||
{
|
||||
rt_kprintf("vbus read err: %d, %d\n", len, rt_get_errno());
|
||||
}
|
||||
|
||||
rt_uint8_t led_value = 1;
|
||||
led_dev->write(led_dev, 1, &led_value, sizeof(led_value));
|
||||
rt_thread_delay(500);
|
||||
led_value = 0;
|
||||
led_dev->write(led_dev, 1, &led_value, sizeof(led_value));
|
||||
rt_thread_delay(500);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,6 +50,5 @@ extern int __bss_end;
|
||||
|
||||
void rt_hw_board_init(void);
|
||||
int rt_hw_board_heap_init(void);
|
||||
int rt_vbus_do_init(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
#ifndef __VBUS_CONF_H__
|
||||
#define __VBUS_CONF_H__
|
||||
|
||||
/* Number of blocks in VBus. The total size of VBus is
|
||||
* RT_VMM_RB_BLK_NR * 64byte * 2. */
|
||||
#define RT_VMM_RB_BLK_NR 20
|
||||
|
||||
/* We don't use the IRQ number to trigger IRQ in this BSP. */
|
||||
#define RT_VBUS_GUEST_VIRQ 0
|
||||
#define RT_VBUS_HOST_VIRQ 0
|
||||
|
||||
#endif /* end of include guard: __VBUS_CONF_H__ */
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2015-01-07 Grissiom add comment
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
|
||||
#ifdef RT_USING_VBUS
|
||||
#include <rtdevice.h>
|
||||
#include <vbus.h>
|
||||
#include <board.h>
|
||||
|
||||
struct rt_vbus_ring rt_vbus_rings[2] rt_section("vbus_ring");
|
||||
|
||||
int rt_vbus_do_init(void)
|
||||
{
|
||||
return rt_vbus_init(&rt_vbus_rings[1], &rt_vbus_rings[0]);
|
||||
}
|
||||
INIT_COMPONENT_EXPORT(rt_vbus_do_init);
|
||||
|
||||
int rt_vbus_hw_init(void)
|
||||
{
|
||||
NVIC_ClearPendingIRQ(M0_M4CORE_IRQn);
|
||||
NVIC_EnableIRQ(M0_M4CORE_IRQn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void M4CORE_IRQHandler(void)
|
||||
{
|
||||
LPC_CREG->M4TXEVENT = 0;
|
||||
rt_vbus_isr(M0_M4CORE_IRQn, RT_NULL);
|
||||
}
|
||||
|
||||
int rt_vbus_hw_eoi(int irqnr, void *param)
|
||||
{
|
||||
/* Nothing to do here as we cleared the interrupt in IRQHandler. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct rt_vbus_dev rt_vbus_chn_devx[] = {
|
||||
{
|
||||
.req =
|
||||
{
|
||||
.prio = 30,
|
||||
.name = "vecho",
|
||||
.is_server = 0,
|
||||
.recv_wm.low = RT_VMM_RB_BLK_NR / 3,
|
||||
.recv_wm.high = RT_VMM_RB_BLK_NR * 2 / 3,
|
||||
.post_wm.low = RT_VMM_RB_BLK_NR / 3,
|
||||
.post_wm.high = RT_VMM_RB_BLK_NR * 2 / 3,
|
||||
}
|
||||
},
|
||||
{
|
||||
.req =
|
||||
{
|
||||
.name = RT_NULL,
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
#endif /* RT_USING_VBUS */
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2015-01-07 Grissiom init commit
|
||||
*/
|
||||
|
||||
#ifndef __VBUS_HW_H__
|
||||
#define __VBUS_HW_H__
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <board.h>
|
||||
|
||||
rt_inline void rt_vbus_tick(unsigned int target_cpu, unsigned int irqnr)
|
||||
{
|
||||
__SEV();
|
||||
}
|
||||
|
||||
/* Read memory barrier. */
|
||||
rt_inline void rt_vbus_smp_rmb(void)
|
||||
{
|
||||
__DMB();
|
||||
}
|
||||
|
||||
/* Write memory barrier. */
|
||||
rt_inline void rt_vbus_smp_wmb(void)
|
||||
{
|
||||
__DSB();
|
||||
}
|
||||
|
||||
/* General memory barrier. */
|
||||
rt_inline void rt_vbus_smp_mb(void)
|
||||
{
|
||||
__DSB();
|
||||
}
|
||||
|
||||
#endif /* __VBUS_HW_H__ */
|
||||
@@ -220,9 +220,6 @@
|
||||
#define RT_LWIP_MSKADDR3 0
|
||||
// </section>
|
||||
|
||||
#define RT_USING_VBUS
|
||||
#define _RT_VBUS_RING_SZ 64
|
||||
#define RT_VBUS_GUEST_VIRQ 0
|
||||
// </RDTConfigurator>
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
#ifndef __VBUS_LOCAL_CONF_H__
|
||||
#define __VBUS_LOCAL_CONF_H__
|
||||
|
||||
#define RT_VBUS_USING_FLOW_CONTROL
|
||||
|
||||
#define RT_VBUS_USING_TESTS
|
||||
|
||||
#endif /* end of include guard: __VBUS_LOCAL_CONF_H__ */
|
||||
@@ -18,10 +18,6 @@
|
||||
#include <shell.h>
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_VBUS
|
||||
#include <vbus.h>
|
||||
#endif
|
||||
|
||||
static const unsigned char _M0_CODE[] rt_section("M0_CODE") = {
|
||||
// #include "M0_CODE.h"
|
||||
};
|
||||
@@ -64,10 +60,6 @@ void rt_init_thread_entry(void *parameter)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_VBUS
|
||||
rt_vbus_do_init();
|
||||
#endif
|
||||
|
||||
_boot_M0();
|
||||
}
|
||||
|
||||
@@ -79,8 +71,6 @@ static void led_thread_entry(void *parameter)
|
||||
{
|
||||
rt_uint8_t led_value;
|
||||
rt_device_t led_dev;
|
||||
rt_device_t vbus_dev;
|
||||
rt_err_t err;
|
||||
|
||||
rt_led_hw_init();
|
||||
|
||||
@@ -91,34 +81,11 @@ static void led_thread_entry(void *parameter)
|
||||
return;
|
||||
}
|
||||
|
||||
vbus_dev = rt_device_find("vecho");
|
||||
if (vbus_dev == RT_NULL)
|
||||
{
|
||||
rt_kprintf("can not find the vbus device\n");
|
||||
return;
|
||||
}
|
||||
|
||||
err = rt_device_open(vbus_dev, RT_DEVICE_OFLAG_RDWR);
|
||||
if (err != RT_EOK)
|
||||
{
|
||||
rt_kprintf("open vbus failed: %d\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
led_value = 0;
|
||||
while (1)
|
||||
{
|
||||
int len;
|
||||
|
||||
led_dev->write(led_dev, 0, &led_value, sizeof(led_value));
|
||||
|
||||
led_value = !led_value;
|
||||
len = rt_device_write(vbus_dev, 0, &led_value, sizeof(led_value));
|
||||
if (len <= 0)
|
||||
{
|
||||
rt_kprintf("vbus write err: %d, %d\n", len, rt_get_errno());
|
||||
}
|
||||
|
||||
rt_thread_delay(1000);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,5 @@ extern int __bss_end;
|
||||
|
||||
void rt_hw_board_init(void);
|
||||
int rt_hw_board_heap_init(void);
|
||||
int rt_vbus_do_init(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
#ifndef __VBUS_CONF_H__
|
||||
#define __VBUS_CONF_H__
|
||||
|
||||
/* Number of blocks in VBus. The total size of VBus is
|
||||
* RT_VMM_RB_BLK_NR * 64byte * 2. */
|
||||
#define RT_VMM_RB_BLK_NR 20
|
||||
|
||||
/* We don't use the IRQ number to trigger IRQ in this BSP. */
|
||||
#define RT_VBUS_GUEST_VIRQ 0
|
||||
#define RT_VBUS_HOST_VIRQ 0
|
||||
|
||||
#endif /* end of include guard: __VBUS_CONF_H__ */
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2015-01-07 Grissiom add comment
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
|
||||
#ifdef RT_USING_VBUS
|
||||
#include <rtdevice.h>
|
||||
#include <vbus.h>
|
||||
#include <board.h>
|
||||
|
||||
struct rt_vbus_ring rt_vbus_rings[2] rt_section("vbus_ring");
|
||||
|
||||
int rt_vbus_do_init(void)
|
||||
{
|
||||
return rt_vbus_init(&rt_vbus_rings[0], &rt_vbus_rings[1]);
|
||||
}
|
||||
INIT_COMPONENT_EXPORT(rt_vbus_do_init);
|
||||
|
||||
int rt_vbus_hw_init(void)
|
||||
{
|
||||
NVIC_ClearPendingIRQ(M0CORE_IRQn);
|
||||
NVIC_EnableIRQ(M0CORE_IRQn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void M0CORE_IRQHandler(void)
|
||||
{
|
||||
LPC_CREG->M0TXEVENT = 0;
|
||||
rt_vbus_isr(M0CORE_IRQn, RT_NULL);
|
||||
}
|
||||
|
||||
int rt_vbus_hw_eoi(int irqnr, void *param)
|
||||
{
|
||||
/* Nothing to do here as we cleared the interrupt in IRQHandler. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct rt_vbus_dev rt_vbus_chn_devx[] = {
|
||||
{
|
||||
.req =
|
||||
{
|
||||
.prio = 30,
|
||||
.name = "vecho",
|
||||
.is_server = 1,
|
||||
.recv_wm.low = RT_VMM_RB_BLK_NR / 3,
|
||||
.recv_wm.high = RT_VMM_RB_BLK_NR * 2 / 3,
|
||||
.post_wm.low = RT_VMM_RB_BLK_NR / 3,
|
||||
.post_wm.high = RT_VMM_RB_BLK_NR * 2 / 3,
|
||||
}
|
||||
},
|
||||
{
|
||||
.req =
|
||||
{
|
||||
.name = RT_NULL,
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
#endif /* RT_USING_VBUS */
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2015-01-07 Grissiom init commit
|
||||
*/
|
||||
|
||||
#ifndef __VBUS_HW_H__
|
||||
#define __VBUS_HW_H__
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <board.h>
|
||||
|
||||
rt_inline void rt_vbus_tick(unsigned int target_cpu, unsigned int irqnr)
|
||||
{
|
||||
__SEV();
|
||||
}
|
||||
|
||||
/* Read memory barrier. */
|
||||
rt_inline void rt_vbus_smp_rmb(void)
|
||||
{
|
||||
__DMB();
|
||||
}
|
||||
|
||||
/* Write memory barrier. */
|
||||
rt_inline void rt_vbus_smp_wmb(void)
|
||||
{
|
||||
__DSB();
|
||||
}
|
||||
|
||||
/* General memory barrier. */
|
||||
rt_inline void rt_vbus_smp_mb(void)
|
||||
{
|
||||
__DSB();
|
||||
}
|
||||
|
||||
#endif /* __VBUS_HW_H__ */
|
||||
@@ -222,10 +222,6 @@
|
||||
#define RT_LWIP_MSKADDR3 0
|
||||
// </section>
|
||||
|
||||
#define RT_USING_VBUS
|
||||
|
||||
#define RT_VBUS_GUEST_VIRQ 0
|
||||
#define _RT_VBUS_RING_SZ 64
|
||||
// </RDTConfigurator>
|
||||
#define RT_CPUS_NR 1
|
||||
#define RT_BACKTRACE_LEVEL_MAX_NR 32
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
#ifndef __VBUS_LOCAL_CONF_H__
|
||||
#define __VBUS_LOCAL_CONF_H__
|
||||
|
||||
#define RT_VBUS_USING_FLOW_CONTROL
|
||||
|
||||
#define RT_VBUS_USING_TESTS
|
||||
|
||||
#endif /* end of include guard: __VBUS_LOCAL_CONF_H__ */
|
||||
@@ -37,7 +37,6 @@ rsource "libc/Kconfig"
|
||||
rsource "net/Kconfig"
|
||||
rsource "mprotect/Kconfig"
|
||||
rsource "utilities/Kconfig"
|
||||
rsource "vbus/Kconfig"
|
||||
endif
|
||||
|
||||
if ARCH_MM_MMU
|
||||
|
||||
@@ -357,33 +357,3 @@ R0.14b (April 17, 2021)
|
||||
Fixed some compiler warnings.
|
||||
|
||||
|
||||
|
||||
R0.15 (November 6, 2022)
|
||||
Changed user provided synchronization functions in order to completely eliminate the platform dependency from FatFs code.
|
||||
FF_SYNC_t is removed from the configuration options.
|
||||
Fixed a potential error in f_mount when FF_FS_REENTRANT.
|
||||
Fixed file lock control FF_FS_LOCK is not mutal excluded when FF_FS_REENTRANT && FF_VOLUMES > 1 is true.
|
||||
Fixed f_mkfs() creates broken exFAT volume when the size of volume is >= 2^32 sectors.
|
||||
Fixed string functions cannot write the unicode characters not in BMP when FF_LFN_UNICODE == 2 (UTF-8).
|
||||
Fixed a compatibility issue in identification of GPT header.
|
||||
|
||||
|
||||
|
||||
R0.15a (November 22, 2024)
|
||||
Fixed a complie error when FF_FS_LOCK != 0.
|
||||
Fixed a potential issue when work FatFs concurrency with FF_FS_REENTRANT, FF_VOLUMES >= 2 and FF_FS_LOCK > 0.
|
||||
Made f_setlabel() accept a volume label in Unix style volume ID when FF_STR_VOLUME_ID == 2.
|
||||
Made FatFs update PercInUse field in exFAT VBR. (A preceding f_getfree() is needed for the accuracy)
|
||||
|
||||
|
||||
|
||||
R0.15b (June 21, 2025)
|
||||
Added support for timestamp of created time. (FF_FS_CRTIME)
|
||||
Fixed FatFs fails to load the FsInfo in FAT32 volumes and the f_getfree always be forced a full FAT scan which takes a long time. (appeared at R0.15a)
|
||||
|
||||
|
||||
|
||||
R0.16 (July 22, 2025)
|
||||
Removed a long-pending limitation that f_getcwd and double-dot .. in the path name did not work on the exFAT volume.
|
||||
Fixed f_readdir cannot detect end of directory and it leads the application process into infinite loop. (appeared at R0.15b)
|
||||
Fixed dot names with terminating separator or duplicated separator are rejected when LFN is not enabled.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FatFs Module Source Files R0.16
|
||||
FatFs Module Source Files R0.14b
|
||||
|
||||
|
||||
FILES
|
||||
|
||||
@@ -999,41 +999,41 @@ DWORD get_fattime(void)
|
||||
}
|
||||
|
||||
#if FF_FS_REENTRANT
|
||||
static rt_mutex_t Mutex[FF_VOLUMES + 1];
|
||||
|
||||
int ff_mutex_create (int vol)
|
||||
int ff_cre_syncobj(BYTE drv, FF_SYNC_t *m)
|
||||
{
|
||||
char name[8];
|
||||
rt_mutex_t mutex;
|
||||
|
||||
rt_snprintf(name, sizeof(name), "fat%d", vol);
|
||||
rt_snprintf(name, sizeof(name), "fat%d", drv);
|
||||
mutex = rt_mutex_create(name, RT_IPC_FLAG_PRIO);
|
||||
if (mutex != RT_NULL)
|
||||
{
|
||||
Mutex[vol] = mutex;
|
||||
*m = mutex;
|
||||
return RT_TRUE;
|
||||
}
|
||||
|
||||
return RT_FALSE;
|
||||
}
|
||||
|
||||
void ff_mutex_delete (int vol)
|
||||
int ff_del_syncobj(FF_SYNC_t m)
|
||||
{
|
||||
if (Mutex[vol] != RT_NULL)
|
||||
rt_mutex_delete(Mutex[vol]);
|
||||
if (m != RT_NULL)
|
||||
rt_mutex_delete(m);
|
||||
|
||||
return RT_TRUE;
|
||||
}
|
||||
|
||||
int ff_mutex_take (int vol)
|
||||
int ff_req_grant(FF_SYNC_t m)
|
||||
{
|
||||
if (rt_mutex_take(Mutex[vol], FF_FS_TIMEOUT) == RT_EOK)
|
||||
if (rt_mutex_take(m, FF_FS_TIMEOUT) == RT_EOK)
|
||||
return RT_TRUE;
|
||||
|
||||
return RT_FALSE;
|
||||
}
|
||||
|
||||
void ff_mutex_give (int vol)
|
||||
void ff_rel_grant(FF_SYNC_t m)
|
||||
{
|
||||
rt_mutex_release(Mutex[vol]);
|
||||
rt_mutex_release(m);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*-----------------------------------------------------------------------/
|
||||
/ Low level disk interface modlue include file (C)ChaN, 2025 /
|
||||
/ Low level disk interface modlue include file (C)ChaN, 2019 /
|
||||
/-----------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _DISKIO_DEFINED
|
||||
@@ -55,7 +55,7 @@ DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);
|
||||
#define CTRL_EJECT 7 /* Eject media */
|
||||
#define CTRL_FORMAT 8 /* Create physical format on the media */
|
||||
|
||||
/* MMC/SDC specific ioctl command (Not used by FatFs) */
|
||||
/* MMC/SDC specific ioctl command */
|
||||
#define MMC_GET_TYPE 10 /* Get card type */
|
||||
#define MMC_GET_CSD 11 /* Get CSD */
|
||||
#define MMC_GET_CID 12 /* Get CID */
|
||||
@@ -65,7 +65,7 @@ DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);
|
||||
#define ISDIO_WRITE 56 /* Write data to SD iSDIO register */
|
||||
#define ISDIO_MRITE 57 /* Masked write data to SD iSDIO register */
|
||||
|
||||
/* ATA/CF specific ioctl command (Not used by FatFs) */
|
||||
/* ATA/CF specific ioctl command */
|
||||
#define ATA_GET_REV 20 /* Get F/W revision */
|
||||
#define ATA_GET_MODEL 21 /* Get model name */
|
||||
#define ATA_GET_SN 22 /* Get serial number */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,8 @@
|
||||
/*----------------------------------------------------------------------------/
|
||||
/ FatFs - Generic FAT Filesystem module R0.16 /
|
||||
/ FatFs - Generic FAT Filesystem module R0.14b /
|
||||
/-----------------------------------------------------------------------------/
|
||||
/
|
||||
/ Copyright (C) 2025, ChaN, all right reserved.
|
||||
/ Copyright (C) 2021, ChaN, all right reserved.
|
||||
/
|
||||
/ FatFs module is an open source software. Redistribution and use of FatFs in
|
||||
/ source and binary forms, with or without modification, are permitted provided
|
||||
@@ -20,16 +20,15 @@
|
||||
|
||||
|
||||
#ifndef FF_DEFINED
|
||||
#define FF_DEFINED 80386 /* Revision ID */
|
||||
#define FF_DEFINED 86631 /* Revision ID */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <rtthread.h>
|
||||
#if !defined(FFCONF_DEF)
|
||||
#include "ffconf.h" /* FatFs configuration options */
|
||||
#endif
|
||||
|
||||
#if FF_DEFINED != FFCONF_DEF
|
||||
#error Wrong configuration file (ffconf.h).
|
||||
#endif
|
||||
@@ -50,18 +49,18 @@ typedef unsigned __int64 QWORD;
|
||||
#include <stdint.h>
|
||||
typedef unsigned int UINT; /* int must be 16-bit or 32-bit */
|
||||
typedef unsigned char BYTE; /* char must be 8-bit */
|
||||
typedef uint16_t WORD; /* 16-bit unsigned */
|
||||
typedef uint32_t DWORD; /* 32-bit unsigned */
|
||||
typedef uint64_t QWORD; /* 64-bit unsigned */
|
||||
typedef WORD WCHAR; /* UTF-16 code unit */
|
||||
typedef uint16_t WORD; /* 16-bit unsigned integer */
|
||||
typedef uint32_t DWORD; /* 32-bit unsigned integer */
|
||||
typedef uint64_t QWORD; /* 64-bit unsigned integer */
|
||||
typedef WORD WCHAR; /* UTF-16 character type */
|
||||
|
||||
#else /* Earlier than C99 */
|
||||
#define FF_INTDEF 1
|
||||
typedef unsigned int UINT; /* int must be 16-bit or 32-bit */
|
||||
typedef unsigned char BYTE; /* char must be 8-bit */
|
||||
typedef unsigned short WORD; /* short must be 16-bit */
|
||||
typedef unsigned long DWORD; /* long must be 32-bit */
|
||||
typedef WORD WCHAR; /* UTF-16 code unit */
|
||||
typedef unsigned short WORD; /* 16-bit unsigned integer */
|
||||
typedef unsigned long DWORD; /* 32-bit unsigned integer */
|
||||
typedef WORD WCHAR; /* UTF-16 character type */
|
||||
#endif
|
||||
|
||||
|
||||
@@ -115,78 +114,66 @@ typedef char TCHAR;
|
||||
|
||||
#if FF_MULTI_PARTITION /* Multiple partition configuration */
|
||||
typedef struct {
|
||||
BYTE pd; /* Associated physical drive */
|
||||
BYTE pt; /* Associated partition (0:Auto detect, 1-4:Forced partition) */
|
||||
BYTE pd; /* Physical drive number */
|
||||
BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */
|
||||
} PARTITION;
|
||||
extern PARTITION VolToPart[]; /* Volume to partition mapping table */
|
||||
extern PARTITION VolToPart[]; /* Volume - Partition mapping table */
|
||||
#endif
|
||||
|
||||
#if FF_STR_VOLUME_ID
|
||||
#ifndef FF_VOLUME_STRS
|
||||
extern const char* VolumeStr[FF_VOLUMES]; /* User defined volume ID table */
|
||||
extern const char* VolumeStr[FF_VOLUMES]; /* User defied volume ID */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* Current working directory structure (FFXCWDS) */
|
||||
|
||||
#if FF_FS_EXFAT && FF_FS_RPATH
|
||||
#if FF_PATH_DEPTH < 1
|
||||
#error FF_PATH_DEPTH must not be zero
|
||||
#endif
|
||||
typedef struct {
|
||||
DWORD d_scl; /* Directory start cluster (0:root dir) */
|
||||
DWORD d_size; /* Size of directory (b7-b0: cluster chain status) (invalid if d_scl == 0) */
|
||||
DWORD nxt_ofs; /* Offset of entry of next dir in this directory (invalid if last link) */
|
||||
} FFXCWDL;
|
||||
typedef struct {
|
||||
UINT depth; /* Current directory depth (0:root dir) */
|
||||
FFXCWDL tbl[FF_PATH_DEPTH + 1]; /* Directory chain of current working directory path */
|
||||
} FFXCWDS;
|
||||
#endif
|
||||
|
||||
|
||||
/* Filesystem object structure (FATFS) */
|
||||
|
||||
typedef struct {
|
||||
BYTE fs_type; /* Filesystem type (0:not mounted) */
|
||||
BYTE pdrv; /* Physical drive that holds this volume */
|
||||
BYTE ldrv; /* Logical drive number (used only when FF_FS_REENTRANT) */
|
||||
BYTE n_fats; /* Number of FATs (1 or 2) */
|
||||
BYTE wflag; /* win[] status (b0:dirty) */
|
||||
BYTE fsi_flag; /* Allocation information control (b7:disabled, b0:dirty) */
|
||||
WORD id; /* Volume mount ID */
|
||||
WORD n_rootdir; /* Number of root directory entries (FAT12/16) */
|
||||
WORD csize; /* Cluster size [sectors] */
|
||||
BYTE fs_type; /* Filesystem type (0:not mounted) */
|
||||
BYTE pdrv; /* Associated physical drive */
|
||||
BYTE n_fats; /* Number of FATs (1 or 2) */
|
||||
BYTE wflag; /* win[] flag (b0:dirty) */
|
||||
BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */
|
||||
WORD id; /* Volume mount ID */
|
||||
WORD n_rootdir; /* Number of root directory entries (FAT12/16) */
|
||||
WORD csize; /* Cluster size [sectors] */
|
||||
#if FF_MAX_SS != FF_MIN_SS
|
||||
WORD ssize; /* Sector size (512, 1024, 2048 or 4096) */
|
||||
WORD ssize; /* Sector size (512, 1024, 2048 or 4096) */
|
||||
#endif
|
||||
#if FF_USE_LFN
|
||||
WCHAR* lfnbuf; /* Pointer to LFN working buffer */
|
||||
WCHAR* lfnbuf; /* LFN working buffer */
|
||||
#endif
|
||||
#if FF_FS_EXFAT
|
||||
BYTE* dirbuf; /* Directory entry block scratchpad buffer for exFAT */
|
||||
#endif
|
||||
#if FF_FS_REENTRANT
|
||||
FF_SYNC_t sobj; /* Identifier of sync object */
|
||||
#endif
|
||||
#if !FF_FS_READONLY
|
||||
DWORD last_clst; /* Last allocated cluster (invalid if >=n_fatent) */
|
||||
DWORD free_clst; /* Number of free clusters (invalid if >=fs->n_fatent-2) */
|
||||
DWORD last_clst; /* Last allocated cluster */
|
||||
DWORD free_clst; /* Number of free clusters */
|
||||
#endif
|
||||
#if FF_FS_RPATH
|
||||
DWORD cdir; /* Current directory start cluster (0:root) */
|
||||
#endif
|
||||
DWORD n_fatent; /* Number of FAT entries (number of clusters + 2) */
|
||||
DWORD fsize; /* Number of sectors per FAT */
|
||||
LBA_t winsect; /* Current sector appearing in the win[] */
|
||||
LBA_t volbase; /* Volume base sector */
|
||||
LBA_t fatbase; /* FAT base sector */
|
||||
LBA_t dirbase; /* Root directory base sector (FAT12/16) or cluster (FAT32/exFAT) */
|
||||
LBA_t database; /* Data base sector */
|
||||
DWORD cdir; /* Current directory start cluster (0:root) */
|
||||
#if FF_FS_EXFAT
|
||||
LBA_t bitbase; /* Allocation bitmap base sector */
|
||||
BYTE* dirbuf; /* Pointer to directory entry block buffer */
|
||||
#if FF_FS_RPATH
|
||||
FFXCWDS xcwds; /* Crrent working directory structure */
|
||||
FFXCWDS xcwds2; /* Working buffer to follow the path */
|
||||
DWORD cdc_scl; /* Containing directory start cluster (invalid when cdir is 0) */
|
||||
DWORD cdc_size; /* b31-b8:Size of containing directory, b7-b0: Chain status */
|
||||
DWORD cdc_ofs; /* Offset in the containing directory (invalid when cdir is 0) */
|
||||
#endif
|
||||
#endif
|
||||
BYTE win[FF_MAX_SS]; /* Disk access window for directory, FAT (and file data in tiny cfg) */
|
||||
DWORD n_fatent; /* Number of FAT entries (number of clusters + 2) */
|
||||
DWORD fsize; /* Size of an FAT [sectors] */
|
||||
LBA_t volbase; /* Volume base sector */
|
||||
LBA_t fatbase; /* FAT base sector */
|
||||
LBA_t dirbase; /* Root directory base sector/cluster */
|
||||
LBA_t database; /* Data base sector */
|
||||
#if FF_FS_EXFAT
|
||||
LBA_t bitbase; /* Allocation bitmap base sector */
|
||||
#endif
|
||||
LBA_t winsect; /* Current sector appearing in the win[] */
|
||||
BYTE win[FF_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
|
||||
} FATFS;
|
||||
|
||||
|
||||
@@ -194,21 +181,21 @@ typedef struct {
|
||||
/* Object ID and allocation information (FFOBJID) */
|
||||
|
||||
typedef struct {
|
||||
FATFS* fs; /* Pointer to the volume holding this object */
|
||||
WORD id; /* Volume mount ID when this object was opened */
|
||||
BYTE attr; /* Object attribute */
|
||||
BYTE stat; /* Object chain status (exFAT: b1-0: =0:not contiguous, =2:contiguous, =3:fragmented in this session, b2:sub-directory stretched) */
|
||||
DWORD sclust; /* Object data cluster (0:no data or root directory) */
|
||||
FSIZE_t objsize; /* Object size (valid when sclust != 0) */
|
||||
FATFS* fs; /* Pointer to the hosting volume of this object */
|
||||
WORD id; /* Hosting volume mount ID */
|
||||
BYTE attr; /* Object attribute */
|
||||
BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous, =3:fragmented in this session, b2:sub-directory stretched) */
|
||||
DWORD sclust; /* Object data start cluster (0:no cluster or root directory) */
|
||||
FSIZE_t objsize; /* Object size (valid when sclust != 0) */
|
||||
#if FF_FS_EXFAT
|
||||
DWORD n_cont; /* Size of first fragment - 1 (valid when stat == 3) */
|
||||
DWORD n_frag; /* Size of last fragment needs to be written to FAT (valid when not zero) */
|
||||
DWORD c_scl; /* Cluster of directory holding this object (valid when sclust != 0) */
|
||||
DWORD c_size; /* Size of directory holding this object (b7-b0: allocation status, valid when c_scl != 0) */
|
||||
DWORD c_ofs; /* Offset of entry in the holding directory */
|
||||
DWORD n_cont; /* Size of first fragment - 1 (valid when stat == 3) */
|
||||
DWORD n_frag; /* Size of last fragment needs to be written to FAT (valid when not zero) */
|
||||
DWORD c_scl; /* Containing directory start cluster (valid when sclust != 0) */
|
||||
DWORD c_size; /* b31-b8:Size of containing directory, b7-b0: Chain status (valid when c_scl != 0) */
|
||||
DWORD c_ofs; /* Offset in the containing directory (valid when file object and sclust != 0) */
|
||||
#endif
|
||||
#if FF_FS_LOCK
|
||||
UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */
|
||||
UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */
|
||||
#endif
|
||||
} FFOBJID;
|
||||
|
||||
@@ -217,18 +204,18 @@ typedef struct {
|
||||
/* File object structure (FIL) */
|
||||
|
||||
typedef struct {
|
||||
FFOBJID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */
|
||||
BYTE flag; /* File status flags */
|
||||
BYTE err; /* Abort flag (error code) */
|
||||
FSIZE_t fptr; /* File read/write pointer (0 on open) */
|
||||
DWORD clust; /* Current cluster of fptr (invalid when fptr is 0) */
|
||||
LBA_t sect; /* Sector number appearing in buf[] (0:invalid) */
|
||||
FFOBJID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */
|
||||
BYTE flag; /* File status flags */
|
||||
BYTE err; /* Abort flag (error code) */
|
||||
FSIZE_t fptr; /* File read/write pointer (Zeroed on file open) */
|
||||
DWORD clust; /* Current cluster of fpter (invalid when fptr is 0) */
|
||||
LBA_t sect; /* Sector number appearing in buf[] (0:invalid) */
|
||||
#if !FF_FS_READONLY
|
||||
LBA_t dir_sect; /* Sector number containing the directory entry (not used in exFAT) */
|
||||
BYTE* dir_ptr; /* Pointer to the directory entry in the win[] (not used in exFAT) */
|
||||
LBA_t dir_sect; /* Sector number containing the directory entry (not used at exFAT) */
|
||||
BYTE* dir_ptr; /* Pointer to the directory entry in the win[] (not used at exFAT) */
|
||||
#endif
|
||||
#if FF_USE_FASTSEEK
|
||||
DWORD* cltbl; /* Pointer to the cluster link map table (nulled on open; set by application) */
|
||||
DWORD* cltbl; /* Pointer to the cluster link map table (nulled on open, set by application) */
|
||||
#endif
|
||||
#if !FF_FS_TINY
|
||||
BYTE buf[FF_MAX_SS]; /* File private data read/write window */
|
||||
@@ -240,44 +227,40 @@ typedef struct {
|
||||
/* Directory object structure (DIR) */
|
||||
|
||||
typedef struct {
|
||||
FFOBJID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */
|
||||
DWORD dptr; /* Current read/write offset */
|
||||
DWORD clust; /* Current cluster */
|
||||
LBA_t sect; /* Current sector (0:no more item to read) */
|
||||
BYTE* dir; /* Pointer to the directory item in the win[] in filesystem object */
|
||||
BYTE fn[12]; /* SFN (in/out) {body[0-7],ext[8-10],status[11]} */
|
||||
FFOBJID obj; /* Object identifier */
|
||||
DWORD dptr; /* Current read/write offset */
|
||||
DWORD clust; /* Current cluster */
|
||||
LBA_t sect; /* Current sector (0:Read operation has terminated) */
|
||||
BYTE* dir; /* Pointer to the directory item in the win[] */
|
||||
BYTE fn[12]; /* SFN (in/out) {body[8],ext[3],status[1]} */
|
||||
#if FF_USE_LFN
|
||||
DWORD blk_ofs; /* Offset of current entry block being processed (0xFFFFFFFF:invalid) */
|
||||
DWORD blk_ofs; /* Offset of current entry block being processed (0xFFFFFFFF:Invalid) */
|
||||
#endif
|
||||
#if FF_USE_FIND
|
||||
const TCHAR *pat; /* Pointer to the name matching pattern */
|
||||
const TCHAR* pat; /* Pointer to the name matching pattern */
|
||||
#endif
|
||||
} DIR;
|
||||
|
||||
|
||||
|
||||
/* File/directory information structure (FILINFO) */
|
||||
/* File information structure (FILINFO) */
|
||||
|
||||
typedef struct {
|
||||
FSIZE_t fsize; /* File size (invalid for directory) */
|
||||
WORD fdate; /* Date of file modification or directory creation */
|
||||
WORD ftime; /* Time of file modification or directory creation */
|
||||
#if FF_FS_CRTIME
|
||||
WORD crdate; /* Date of object createion */
|
||||
WORD crtime; /* Time of object createion */
|
||||
#endif
|
||||
BYTE fattrib; /* Object attribute */
|
||||
FSIZE_t fsize; /* File size */
|
||||
WORD fdate; /* Modified date */
|
||||
WORD ftime; /* Modified time */
|
||||
BYTE fattrib; /* File attribute */
|
||||
#if FF_USE_LFN
|
||||
TCHAR altname[FF_SFN_BUF + 1];/* Alternative object name */
|
||||
TCHAR fname[FF_LFN_BUF + 1]; /* Primary object name */
|
||||
TCHAR altname[FF_SFN_BUF + 1];/* Altenative file name */
|
||||
TCHAR fname[FF_LFN_BUF + 1]; /* Primary file name */
|
||||
#else
|
||||
TCHAR fname[12 + 1]; /* Object name */
|
||||
TCHAR fname[12 + 1]; /* File name */
|
||||
#endif
|
||||
} FILINFO;
|
||||
|
||||
|
||||
|
||||
/* Format parameter structure (MKFS_PARM) used for f_mkfs() */
|
||||
/* Format parameter structure (MKFS_PARM) */
|
||||
|
||||
typedef struct {
|
||||
BYTE fmt; /* Format option (FM_FAT, FM_FAT32, FM_EXFAT and FM_SFD) */
|
||||
@@ -292,34 +275,32 @@ typedef struct {
|
||||
/* File function return code (FRESULT) */
|
||||
|
||||
typedef enum {
|
||||
FR_OK = 0, /* (0) Function succeeded */
|
||||
FR_OK = 0, /* (0) Succeeded */
|
||||
FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */
|
||||
FR_INT_ERR, /* (2) Assertion failed */
|
||||
FR_NOT_READY, /* (3) The physical drive does not work */
|
||||
FR_NOT_READY, /* (3) The physical drive cannot work */
|
||||
FR_NO_FILE, /* (4) Could not find the file */
|
||||
FR_NO_PATH, /* (5) Could not find the path */
|
||||
FR_INVALID_NAME, /* (6) The path name format is invalid */
|
||||
FR_DENIED, /* (7) Access denied due to a prohibited access or directory full */
|
||||
FR_EXIST, /* (8) Access denied due to a prohibited access */
|
||||
FR_DENIED, /* (7) Access denied due to prohibited access or directory full */
|
||||
FR_EXIST, /* (8) Access denied due to prohibited access */
|
||||
FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */
|
||||
FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */
|
||||
FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */
|
||||
FR_NOT_ENABLED, /* (12) The volume has no work area */
|
||||
FR_NO_FILESYSTEM, /* (13) Could not find a valid FAT volume */
|
||||
FR_MKFS_ABORTED, /* (14) The f_mkfs function aborted due to some problem */
|
||||
FR_TIMEOUT, /* (15) Could not take control of the volume within defined period */
|
||||
FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */
|
||||
FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any problem */
|
||||
FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */
|
||||
FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */
|
||||
FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated, given buffer size is insufficient or too deep path */
|
||||
FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */
|
||||
FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > FF_FS_LOCK */
|
||||
FR_INVALID_PARAMETER /* (19) Given parameter is invalid */
|
||||
} FRESULT;
|
||||
|
||||
|
||||
|
||||
|
||||
/*--------------------------------------------------------------*/
|
||||
/* FatFs Module Application Interface */
|
||||
/*--------------------------------------------------------------*/
|
||||
/* FatFs module application interface */
|
||||
|
||||
FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a file */
|
||||
FRESULT f_close (FIL* fp); /* Close an open file object */
|
||||
@@ -357,8 +338,6 @@ int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */
|
||||
int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */
|
||||
TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */
|
||||
|
||||
/* Some API fucntions are implemented as macro */
|
||||
|
||||
#define f_eof(fp) ((int)((fp)->fptr == (fp)->obj.objsize))
|
||||
#define f_error(fp) ((fp)->err)
|
||||
#define f_tell(fp) ((fp)->fptr)
|
||||
@@ -372,45 +351,40 @@ TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the fil
|
||||
|
||||
|
||||
/*--------------------------------------------------------------*/
|
||||
/* Additional Functions */
|
||||
/*--------------------------------------------------------------*/
|
||||
/* Additional user defined functions */
|
||||
|
||||
/* RTC function (provided by user) */
|
||||
/* RTC function */
|
||||
#if !FF_FS_READONLY && !FF_FS_NORTC
|
||||
DWORD get_fattime (void); /* Get current time */
|
||||
DWORD get_fattime (void);
|
||||
#endif
|
||||
|
||||
|
||||
/* LFN support functions (defined in ffunicode.c) */
|
||||
|
||||
#if FF_USE_LFN >= 1
|
||||
/* LFN support functions */
|
||||
#if FF_USE_LFN >= 1 /* Code conversion (defined in unicode.c) */
|
||||
WCHAR ff_oem2uni (WCHAR oem, WORD cp); /* OEM code to Unicode conversion */
|
||||
WCHAR ff_uni2oem (DWORD uni, WORD cp); /* Unicode to OEM code conversion */
|
||||
DWORD ff_wtoupper (DWORD uni); /* Unicode upper-case conversion */
|
||||
#endif
|
||||
|
||||
|
||||
/* O/S dependent functions (samples available in ffsystem.c) */
|
||||
|
||||
#if FF_USE_LFN == 3 /* Dynamic memory allocation */
|
||||
void* ff_memalloc (UINT msize); /* Allocate memory block */
|
||||
void ff_memfree (void* mblock); /* Free memory block */
|
||||
#if FF_USE_LFN == 3 /* Dynamic memory allocation */
|
||||
void* ff_memalloc (UINT msize); /* Allocate memory block */
|
||||
void ff_memfree (void* mblock); /* Free memory block */
|
||||
#endif
|
||||
#if FF_FS_REENTRANT /* Sync functions */
|
||||
int ff_mutex_create (int vol); /* Create a sync object */
|
||||
void ff_mutex_delete (int vol); /* Delete a sync object */
|
||||
int ff_mutex_take (int vol); /* Lock sync object */
|
||||
void ff_mutex_give (int vol); /* Unlock sync object */
|
||||
|
||||
/* Sync functions */
|
||||
#if FF_FS_REENTRANT
|
||||
int ff_cre_syncobj (BYTE vol, FF_SYNC_t* sobj); /* Create a sync object */
|
||||
int ff_req_grant (FF_SYNC_t sobj); /* Lock sync object */
|
||||
void ff_rel_grant (FF_SYNC_t sobj); /* Unlock sync object */
|
||||
int ff_del_syncobj (FF_SYNC_t sobj); /* Delete a sync object */
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
/*--------------------------------------------------------------*/
|
||||
/* Flags and Offset Address */
|
||||
/*--------------------------------------------------------------*/
|
||||
/* Flags and offset address */
|
||||
|
||||
/* File access mode and open method flags (3rd argument of f_open function) */
|
||||
|
||||
/* File access mode and open method flags (3rd argument of f_open) */
|
||||
#define FA_READ 0x01
|
||||
#define FA_WRITE 0x02
|
||||
#define FA_OPEN_EXISTING 0x00
|
||||
@@ -419,10 +393,10 @@ void ff_mutex_give (int vol); /* Unlock sync object */
|
||||
#define FA_OPEN_ALWAYS 0x10
|
||||
#define FA_OPEN_APPEND 0x30
|
||||
|
||||
/* Fast seek controls (2nd argument of f_lseek function) */
|
||||
/* Fast seek controls (2nd argument of f_lseek) */
|
||||
#define CREATE_LINKMAP ((FSIZE_t)0 - 1)
|
||||
|
||||
/* Format options (2nd argument of f_mkfs function) */
|
||||
/* Format options (2nd argument of f_mkfs) */
|
||||
#define FM_FAT 0x01
|
||||
#define FM_FAT32 0x02
|
||||
#define FM_EXFAT 0x04
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ Configurations of FatFs Module
|
||||
/ FatFs Functional Configurations
|
||||
/---------------------------------------------------------------------------*/
|
||||
|
||||
#define FFCONF_DEF 80386 /* Revision ID */
|
||||
#define FFCONF_DEF 86631 /* Revision ID */
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ Function Configurations
|
||||
@@ -31,36 +31,36 @@
|
||||
|
||||
|
||||
#define FF_USE_MKFS 1
|
||||
/* This option switches f_mkfs(). (0:Disable or 1:Enable) */
|
||||
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
|
||||
|
||||
|
||||
#define FF_USE_FASTSEEK 1
|
||||
/* This option switches fast seek feature. (0:Disable or 1:Enable) */
|
||||
/* This option switches fast seek function. (0:Disable or 1:Enable) */
|
||||
|
||||
|
||||
#define FF_USE_EXPAND 0
|
||||
/* This option switches f_expand(). (0:Disable or 1:Enable) */
|
||||
/* This option switches f_expand function. (0:Disable or 1:Enable) */
|
||||
|
||||
|
||||
#define FF_USE_CHMOD 0
|
||||
/* This option switches attribute control API functions, f_chmod() and f_utime().
|
||||
/* This option switches attribute manipulation functions, f_chmod() and f_utime().
|
||||
/ (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */
|
||||
|
||||
|
||||
#define FF_USE_LABEL 0
|
||||
/* This option switches volume label API functions, f_getlabel() and f_setlabel().
|
||||
/* This option switches volume label functions, f_getlabel() and f_setlabel().
|
||||
/ (0:Disable or 1:Enable) */
|
||||
|
||||
|
||||
#define FF_USE_FORWARD 0
|
||||
/* This option switches f_forward(). (0:Disable or 1:Enable) */
|
||||
/* This option switches f_forward() function. (0:Disable or 1:Enable) */
|
||||
|
||||
|
||||
#define FF_USE_STRFUNC 0
|
||||
#define FF_PRINT_LLI 0
|
||||
#define FF_PRINT_FLOAT 0
|
||||
#define FF_STRF_ENCODE 3
|
||||
/* FF_USE_STRFUNC switches string API functions, f_gets(), f_putc(), f_puts() and
|
||||
/* FF_USE_STRFUNC switches string functions, f_gets(), f_putc(), f_puts() and
|
||||
/ f_printf().
|
||||
/
|
||||
/ 0: Disable. FF_PRINT_LLI, FF_PRINT_FLOAT and FF_STRF_ENCODE have no effect.
|
||||
@@ -68,8 +68,8 @@
|
||||
/ 2: Enable with LF-CRLF conversion.
|
||||
/
|
||||
/ FF_PRINT_LLI = 1 makes f_printf() support long long argument and FF_PRINT_FLOAT = 1/2
|
||||
/ makes f_printf() support floating point argument. These features want C99 or later.
|
||||
/ When FF_LFN_UNICODE >= 1 with LFN enabled, string API functions convert the character
|
||||
makes f_printf() support floating point argument. These features want C99 or later.
|
||||
/ When FF_LFN_UNICODE >= 1 with LFN enabled, string functions convert the character
|
||||
/ encoding in it. FF_STRF_ENCODE selects assumption of character encoding ON THE FILE
|
||||
/ to be read/written via those functions.
|
||||
/
|
||||
@@ -127,15 +127,15 @@
|
||||
/* 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.
|
||||
/ 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 feature
|
||||
/ 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 the LFN
|
||||
/ be in range of 12 to 255. It is recommended to be set it 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
|
||||
@@ -176,26 +176,14 @@
|
||||
|
||||
|
||||
#define FF_FS_RPATH 0
|
||||
/* This option configures support for relative path feature.
|
||||
/* This option configures support for relative path.
|
||||
/
|
||||
/ 0: Disable relative path and remove related API functions.
|
||||
/ 1: Enable relative path and dot names. f_chdir() and f_chdrive() are available.
|
||||
/ 2: f_getcwd() is available in addition to 1.
|
||||
/ 0: Disable relative path and remove related functions.
|
||||
/ 1: Enable relative path. f_chdir() and f_chdrive() are available.
|
||||
/ 2: f_getcwd() function is available in addition to 1.
|
||||
*/
|
||||
|
||||
|
||||
#define FF_PATH_DEPTH 10
|
||||
/* This option defines maximum depth of directory in the exFAT volume. It is NOT
|
||||
/ relevant to FAT/FAT32 volume.
|
||||
/ For example, FF_PATH_DEPTH = 3 will able to follow a path "/dir1/dir2/dir3/file"
|
||||
/ but a sub-directory in the dir3 will not able to be followed and set current
|
||||
/ directory.
|
||||
/ The size of filesystem object (FATFS) increases FF_PATH_DEPTH * 24 bytes.
|
||||
/ When FF_FS_EXFAT == 0 or FF_FS_RPATH == 0, this option has no effect.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ Drive/Volume Configurations
|
||||
/---------------------------------------------------------------------------*/
|
||||
@@ -213,10 +201,10 @@
|
||||
/* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings.
|
||||
/ When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive
|
||||
/ number in the path name. FF_VOLUME_STRS defines the volume ID strings for each
|
||||
/ logical drive. Number of items must not be less than FF_VOLUMES. Valid
|
||||
/ logical drives. Number of items must not be less than FF_VOLUMES. Valid
|
||||
/ characters for the volume ID strings are A-Z, a-z and 0-9, however, they are
|
||||
/ compared in case-insensitive. If FF_STR_VOLUME_ID >= 1 and FF_VOLUME_STRS is
|
||||
/ not defined, a user defined volume string table is needed as:
|
||||
/ not defined, a user defined volume string table needs to be defined as:
|
||||
/
|
||||
/ const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb",...
|
||||
*/
|
||||
@@ -226,9 +214,9 @@
|
||||
/* This option switches support for multiple volumes on the physical drive.
|
||||
/ By default (0), each logical drive number is bound to the same physical drive
|
||||
/ number and only an FAT volume found on the physical drive will be mounted.
|
||||
/ When this feature is enabled (1), each logical drive number can be bound to
|
||||
/ When this function is enabled (1), each logical drive number can be bound to
|
||||
/ arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk()
|
||||
/ will be available. */
|
||||
/ funciton will be available. */
|
||||
|
||||
|
||||
#define FF_MIN_SS 512
|
||||
@@ -240,8 +228,8 @@
|
||||
/* This set of options configures the range of sector size to be supported. (512,
|
||||
/ 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and
|
||||
/ harddisk, but a larger value may be required for on-board flash memory and some
|
||||
/ type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is
|
||||
/ configured for variable sector size mode and disk_ioctl() needs to implement
|
||||
/ type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is configured
|
||||
/ for variable sector size mode and disk_ioctl() function needs to implement
|
||||
/ GET_SECTOR_SIZE command. */
|
||||
|
||||
|
||||
@@ -251,14 +239,14 @@
|
||||
|
||||
|
||||
#define FF_MIN_GPT 0x10000000
|
||||
/* Minimum number of sectors to switch GPT as partitioning format in f_mkfs() and
|
||||
/ f_fdisk(). 2^32 sectors maximum. This option has no effect when FF_LBA64 == 0. */
|
||||
/* Minimum number of sectors to switch GPT as partitioning format in f_mkfs and
|
||||
/ f_fdisk function. 0x100000000 max. This option has no effect when FF_LBA64 == 0. */
|
||||
|
||||
|
||||
#define FF_USE_TRIM 0
|
||||
/* This option switches support for ATA-TRIM. (0:Disable or 1:Enable)
|
||||
/ To enable this feature, also CTRL_TRIM command should be implemented to
|
||||
/ the disk_ioctl(). */
|
||||
/ To enable Trim function, also CTRL_TRIM command should be implemented to the
|
||||
/ disk_ioctl() function. */
|
||||
|
||||
|
||||
|
||||
@@ -268,7 +256,7 @@
|
||||
|
||||
#define FF_FS_TINY 0
|
||||
/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny)
|
||||
/ At the tiny configuration, size of file object (FIL) is reduced FF_MAX_SS bytes.
|
||||
/ At the tiny configuration, size of file object (FIL) is shrinked FF_MAX_SS bytes.
|
||||
/ Instead of private sector buffer eliminated from the file object, common sector
|
||||
/ buffer in the filesystem object (FATFS) is used for the file data transfer. */
|
||||
|
||||
@@ -285,25 +273,20 @@
|
||||
#define FF_FS_NORTC 0
|
||||
#define FF_NORTC_MON 1
|
||||
#define FF_NORTC_MDAY 1
|
||||
#define FF_NORTC_YEAR 2025
|
||||
/* The option FF_FS_NORTC switches timestamp feature. If the system does not have
|
||||
/ an RTC or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable the
|
||||
/ timestamp feature. Every object modified by FatFs will have a fixed timestamp
|
||||
#define FF_NORTC_YEAR 2020
|
||||
/* The option FF_FS_NORTC switches timestamp functiton. If the system does not have
|
||||
/ any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable
|
||||
/ the timestamp function. Every object modified by FatFs will have a fixed timestamp
|
||||
/ defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time.
|
||||
/ To enable timestamp function (FF_FS_NORTC = 0), get_fattime() need to be added
|
||||
/ to the project to read current time form real-time clock. FF_NORTC_MON,
|
||||
/ To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be
|
||||
/ added to the project to read current time form real-time clock. FF_NORTC_MON,
|
||||
/ FF_NORTC_MDAY and FF_NORTC_YEAR have no effect.
|
||||
/ These options have no effect in read-only configuration (FF_FS_READONLY = 1). */
|
||||
|
||||
|
||||
#define FF_FS_CRTIME 0
|
||||
/* This option enables(1)/disables(0) the timestamp of the file created. When
|
||||
/ set 1, the file created time is available in FILINFO structure. */
|
||||
|
||||
|
||||
#define FF_FS_NOFSINFO 0
|
||||
/* If you need to know the correct free space on the FAT32 volume, set bit 0 of
|
||||
/ this option, and f_getfree() on the first time after volume mount will force
|
||||
/* If you need to know correct free space on the FAT32 volume, set bit 0 of this
|
||||
/ option, and f_getfree() function at first time after volume mount will force
|
||||
/ a full FAT scan. Bit 1 controls the use of last allocated cluster number.
|
||||
/
|
||||
/ bit0=0: Use free cluster count in the FSINFO if available.
|
||||
@@ -340,16 +323,19 @@
|
||||
/* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs
|
||||
/ module itself. Note that regardless of this option, file access to different
|
||||
/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs()
|
||||
/ and f_fdisk(), are always not re-entrant. Only file/directory access to
|
||||
/ the same volume is under control of this featuer.
|
||||
/ and f_fdisk() function, are always not re-entrant. Only file/directory access
|
||||
/ to the same volume is under control of this function.
|
||||
/
|
||||
/ 0: Disable re-entrancy. FF_FS_TIMEOUT have no effect.
|
||||
/ 0: Disable re-entrancy. FF_FS_TIMEOUT and FF_SYNC_t have no effect.
|
||||
/ 1: Enable re-entrancy. Also user provided synchronization handlers,
|
||||
/ ff_mutex_create(), ff_mutex_delete(), ff_mutex_take() and ff_mutex_give(),
|
||||
/ must be added to the project. Samples are available in ffsystem.c.
|
||||
/ ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj()
|
||||
/ function, must be added to the project. Samples are available in
|
||||
/ option/syscall.c.
|
||||
/
|
||||
/ The FF_FS_TIMEOUT defines timeout period in unit of O/S time tick.
|
||||
*/
|
||||
/ The FF_FS_TIMEOUT defines timeout period in unit of time tick.
|
||||
/ The FF_SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*,
|
||||
/ SemaphoreHandle_t and etc. A header file for O/S definitions needs to be
|
||||
/ included somewhere in the scope of ff.h. */
|
||||
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -367,23 +367,3 @@ R0.15 (November 6, 2022)
|
||||
Fixed string functions cannot write the unicode characters not in BMP when FF_LFN_UNICODE == 2 (UTF-8).
|
||||
Fixed a compatibility issue in identification of GPT header.
|
||||
|
||||
|
||||
|
||||
R0.15a (November 22, 2024)
|
||||
Fixed a complie error when FF_FS_LOCK != 0.
|
||||
Fixed a potential issue when work FatFs concurrency with FF_FS_REENTRANT, FF_VOLUMES >= 2 and FF_FS_LOCK > 0.
|
||||
Made f_setlabel() accept a volume label in Unix style volume ID when FF_STR_VOLUME_ID == 2.
|
||||
Made FatFs update PercInUse field in exFAT VBR. (A preceding f_getfree() is needed for the accuracy)
|
||||
|
||||
|
||||
|
||||
R0.15b (June 21, 2025)
|
||||
Added support for timestamp of created time. (FF_FS_CRTIME)
|
||||
Fixed FatFs fails to load the FsInfo in FAT32 volumes and the f_getfree always be forced a full FAT scan which takes a long time. (appeared at R0.15a)
|
||||
|
||||
|
||||
|
||||
R0.16 (July 22, 2025)
|
||||
Removed a long-pending limitation that f_getcwd and double-dot .. in the path name did not work on the exFAT volume.
|
||||
Fixed f_readdir cannot detect end of directory and it leads the application process into infinite loop. (appeared at R0.15b)
|
||||
Fixed dot names with terminating separator or duplicated separator are rejected when LFN is not enabled.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FatFs Module Source Files R0.16
|
||||
FatFs Module Source Files R0.15
|
||||
|
||||
|
||||
FILES
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*-----------------------------------------------------------------------/
|
||||
/ Low level disk interface modlue include file (C)ChaN, 2025 /
|
||||
/ Low level disk interface modlue include file (C)ChaN, 2019 /
|
||||
/-----------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _DISKIO_DEFINED
|
||||
@@ -55,7 +55,7 @@ DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);
|
||||
#define CTRL_EJECT 7 /* Eject media */
|
||||
#define CTRL_FORMAT 8 /* Create physical format on the media */
|
||||
|
||||
/* MMC/SDC specific ioctl command (Not used by FatFs) */
|
||||
/* MMC/SDC specific ioctl command */
|
||||
#define MMC_GET_TYPE 10 /* Get card type */
|
||||
#define MMC_GET_CSD 11 /* Get CSD */
|
||||
#define MMC_GET_CID 12 /* Get CID */
|
||||
@@ -65,7 +65,7 @@ DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);
|
||||
#define ISDIO_WRITE 56 /* Write data to SD iSDIO register */
|
||||
#define ISDIO_MRITE 57 /* Masked write data to SD iSDIO register */
|
||||
|
||||
/* ATA/CF specific ioctl command (Not used by FatFs) */
|
||||
/* ATA/CF specific ioctl command */
|
||||
#define ATA_GET_REV 20 /* Get F/W revision */
|
||||
#define ATA_GET_MODEL 21 /* Get model name */
|
||||
#define ATA_GET_SN 22 /* Get serial number */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,8 @@
|
||||
/*----------------------------------------------------------------------------/
|
||||
/ FatFs - Generic FAT Filesystem module R0.16 /
|
||||
/ FatFs - Generic FAT Filesystem module R0.15 /
|
||||
/-----------------------------------------------------------------------------/
|
||||
/
|
||||
/ Copyright (C) 2025, ChaN, all right reserved.
|
||||
/ Copyright (C) 2022, ChaN, all right reserved.
|
||||
/
|
||||
/ FatFs module is an open source software. Redistribution and use of FatFs in
|
||||
/ source and binary forms, with or without modification, are permitted provided
|
||||
@@ -20,16 +20,15 @@
|
||||
|
||||
|
||||
#ifndef FF_DEFINED
|
||||
#define FF_DEFINED 80386 /* Revision ID */
|
||||
#define FF_DEFINED 80286 /* Revision ID */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <rtthread.h>
|
||||
#if !defined(FFCONF_DEF)
|
||||
#include "ffconf.h" /* FatFs configuration options */
|
||||
#endif
|
||||
|
||||
#if FF_DEFINED != FFCONF_DEF
|
||||
#error Wrong configuration file (ffconf.h).
|
||||
#endif
|
||||
@@ -50,18 +49,18 @@ typedef unsigned __int64 QWORD;
|
||||
#include <stdint.h>
|
||||
typedef unsigned int UINT; /* int must be 16-bit or 32-bit */
|
||||
typedef unsigned char BYTE; /* char must be 8-bit */
|
||||
typedef uint16_t WORD; /* 16-bit unsigned */
|
||||
typedef uint32_t DWORD; /* 32-bit unsigned */
|
||||
typedef uint64_t QWORD; /* 64-bit unsigned */
|
||||
typedef WORD WCHAR; /* UTF-16 code unit */
|
||||
typedef uint16_t WORD; /* 16-bit unsigned integer */
|
||||
typedef uint32_t DWORD; /* 32-bit unsigned integer */
|
||||
typedef uint64_t QWORD; /* 64-bit unsigned integer */
|
||||
typedef WORD WCHAR; /* UTF-16 character type */
|
||||
|
||||
#else /* Earlier than C99 */
|
||||
#define FF_INTDEF 1
|
||||
typedef unsigned int UINT; /* int must be 16-bit or 32-bit */
|
||||
typedef unsigned char BYTE; /* char must be 8-bit */
|
||||
typedef unsigned short WORD; /* short must be 16-bit */
|
||||
typedef unsigned long DWORD; /* long must be 32-bit */
|
||||
typedef WORD WCHAR; /* UTF-16 code unit */
|
||||
typedef unsigned short WORD; /* 16-bit unsigned integer */
|
||||
typedef unsigned long DWORD; /* 32-bit unsigned integer */
|
||||
typedef WORD WCHAR; /* UTF-16 character type */
|
||||
#endif
|
||||
|
||||
|
||||
@@ -115,78 +114,64 @@ typedef char TCHAR;
|
||||
|
||||
#if FF_MULTI_PARTITION /* Multiple partition configuration */
|
||||
typedef struct {
|
||||
BYTE pd; /* Associated physical drive */
|
||||
BYTE pt; /* Associated partition (0:Auto detect, 1-4:Forced partition) */
|
||||
BYTE pd; /* Physical drive number */
|
||||
BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */
|
||||
} PARTITION;
|
||||
extern PARTITION VolToPart[]; /* Volume to partition mapping table */
|
||||
extern PARTITION VolToPart[]; /* Volume - Partition mapping table */
|
||||
#endif
|
||||
|
||||
#if FF_STR_VOLUME_ID
|
||||
#ifndef FF_VOLUME_STRS
|
||||
extern const char* VolumeStr[FF_VOLUMES]; /* User defined volume ID table */
|
||||
extern const char* VolumeStr[FF_VOLUMES]; /* User defied volume ID */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* Current working directory structure (FFXCWDS) */
|
||||
|
||||
#if FF_FS_EXFAT && FF_FS_RPATH
|
||||
#if FF_PATH_DEPTH < 1
|
||||
#error FF_PATH_DEPTH must not be zero
|
||||
#endif
|
||||
typedef struct {
|
||||
DWORD d_scl; /* Directory start cluster (0:root dir) */
|
||||
DWORD d_size; /* Size of directory (b7-b0: cluster chain status) (invalid if d_scl == 0) */
|
||||
DWORD nxt_ofs; /* Offset of entry of next dir in this directory (invalid if last link) */
|
||||
} FFXCWDL;
|
||||
typedef struct {
|
||||
UINT depth; /* Current directory depth (0:root dir) */
|
||||
FFXCWDL tbl[FF_PATH_DEPTH + 1]; /* Directory chain of current working directory path */
|
||||
} FFXCWDS;
|
||||
#endif
|
||||
|
||||
|
||||
/* Filesystem object structure (FATFS) */
|
||||
|
||||
typedef struct {
|
||||
BYTE fs_type; /* Filesystem type (0:not mounted) */
|
||||
BYTE pdrv; /* Physical drive that holds this volume */
|
||||
BYTE ldrv; /* Logical drive number (used only when FF_FS_REENTRANT) */
|
||||
BYTE n_fats; /* Number of FATs (1 or 2) */
|
||||
BYTE wflag; /* win[] status (b0:dirty) */
|
||||
BYTE fsi_flag; /* Allocation information control (b7:disabled, b0:dirty) */
|
||||
WORD id; /* Volume mount ID */
|
||||
WORD n_rootdir; /* Number of root directory entries (FAT12/16) */
|
||||
WORD csize; /* Cluster size [sectors] */
|
||||
BYTE fs_type; /* Filesystem type (0:not mounted) */
|
||||
BYTE pdrv; /* Volume hosting physical drive */
|
||||
BYTE ldrv; /* Logical drive number (used only when FF_FS_REENTRANT) */
|
||||
BYTE n_fats; /* Number of FATs (1 or 2) */
|
||||
BYTE wflag; /* win[] status (b0:dirty) */
|
||||
BYTE fsi_flag; /* FSINFO status (b7:disabled, b0:dirty) */
|
||||
WORD id; /* Volume mount ID */
|
||||
WORD n_rootdir; /* Number of root directory entries (FAT12/16) */
|
||||
WORD csize; /* Cluster size [sectors] */
|
||||
#if FF_MAX_SS != FF_MIN_SS
|
||||
WORD ssize; /* Sector size (512, 1024, 2048 or 4096) */
|
||||
WORD ssize; /* Sector size (512, 1024, 2048 or 4096) */
|
||||
#endif
|
||||
#if FF_USE_LFN
|
||||
WCHAR* lfnbuf; /* Pointer to LFN working buffer */
|
||||
WCHAR* lfnbuf; /* LFN working buffer */
|
||||
#endif
|
||||
#if FF_FS_EXFAT
|
||||
BYTE* dirbuf; /* Directory entry block scratchpad buffer for exFAT */
|
||||
#endif
|
||||
#if !FF_FS_READONLY
|
||||
DWORD last_clst; /* Last allocated cluster (invalid if >=n_fatent) */
|
||||
DWORD free_clst; /* Number of free clusters (invalid if >=fs->n_fatent-2) */
|
||||
DWORD last_clst; /* Last allocated cluster */
|
||||
DWORD free_clst; /* Number of free clusters */
|
||||
#endif
|
||||
#if FF_FS_RPATH
|
||||
DWORD cdir; /* Current directory start cluster (0:root) */
|
||||
#endif
|
||||
DWORD n_fatent; /* Number of FAT entries (number of clusters + 2) */
|
||||
DWORD fsize; /* Number of sectors per FAT */
|
||||
LBA_t winsect; /* Current sector appearing in the win[] */
|
||||
LBA_t volbase; /* Volume base sector */
|
||||
LBA_t fatbase; /* FAT base sector */
|
||||
LBA_t dirbase; /* Root directory base sector (FAT12/16) or cluster (FAT32/exFAT) */
|
||||
LBA_t database; /* Data base sector */
|
||||
DWORD cdir; /* Current directory start cluster (0:root) */
|
||||
#if FF_FS_EXFAT
|
||||
LBA_t bitbase; /* Allocation bitmap base sector */
|
||||
BYTE* dirbuf; /* Pointer to directory entry block buffer */
|
||||
#if FF_FS_RPATH
|
||||
FFXCWDS xcwds; /* Crrent working directory structure */
|
||||
FFXCWDS xcwds2; /* Working buffer to follow the path */
|
||||
DWORD cdc_scl; /* Containing directory start cluster (invalid when cdir is 0) */
|
||||
DWORD cdc_size; /* b31-b8:Size of containing directory, b7-b0: Chain status */
|
||||
DWORD cdc_ofs; /* Offset in the containing directory (invalid when cdir is 0) */
|
||||
#endif
|
||||
#endif
|
||||
BYTE win[FF_MAX_SS]; /* Disk access window for directory, FAT (and file data in tiny cfg) */
|
||||
DWORD n_fatent; /* Number of FAT entries (number of clusters + 2) */
|
||||
DWORD fsize; /* Number of sectors per FAT */
|
||||
LBA_t volbase; /* Volume base sector */
|
||||
LBA_t fatbase; /* FAT base sector */
|
||||
LBA_t dirbase; /* Root directory base sector (FAT12/16) or cluster (FAT32/exFAT) */
|
||||
LBA_t database; /* Data base sector */
|
||||
#if FF_FS_EXFAT
|
||||
LBA_t bitbase; /* Allocation bitmap base sector */
|
||||
#endif
|
||||
LBA_t winsect; /* Current sector appearing in the win[] */
|
||||
BYTE win[FF_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
|
||||
} FATFS;
|
||||
|
||||
|
||||
@@ -194,21 +179,21 @@ typedef struct {
|
||||
/* Object ID and allocation information (FFOBJID) */
|
||||
|
||||
typedef struct {
|
||||
FATFS* fs; /* Pointer to the volume holding this object */
|
||||
WORD id; /* Volume mount ID when this object was opened */
|
||||
BYTE attr; /* Object attribute */
|
||||
BYTE stat; /* Object chain status (exFAT: b1-0: =0:not contiguous, =2:contiguous, =3:fragmented in this session, b2:sub-directory stretched) */
|
||||
DWORD sclust; /* Object data cluster (0:no data or root directory) */
|
||||
FSIZE_t objsize; /* Object size (valid when sclust != 0) */
|
||||
FATFS* fs; /* Pointer to the hosting volume of this object */
|
||||
WORD id; /* Hosting volume's mount ID */
|
||||
BYTE attr; /* Object attribute */
|
||||
BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous, =3:fragmented in this session, b2:sub-directory stretched) */
|
||||
DWORD sclust; /* Object data start cluster (0:no cluster or root directory) */
|
||||
FSIZE_t objsize; /* Object size (valid when sclust != 0) */
|
||||
#if FF_FS_EXFAT
|
||||
DWORD n_cont; /* Size of first fragment - 1 (valid when stat == 3) */
|
||||
DWORD n_frag; /* Size of last fragment needs to be written to FAT (valid when not zero) */
|
||||
DWORD c_scl; /* Cluster of directory holding this object (valid when sclust != 0) */
|
||||
DWORD c_size; /* Size of directory holding this object (b7-b0: allocation status, valid when c_scl != 0) */
|
||||
DWORD c_ofs; /* Offset of entry in the holding directory */
|
||||
DWORD n_cont; /* Size of first fragment - 1 (valid when stat == 3) */
|
||||
DWORD n_frag; /* Size of last fragment needs to be written to FAT (valid when not zero) */
|
||||
DWORD c_scl; /* Containing directory start cluster (valid when sclust != 0) */
|
||||
DWORD c_size; /* b31-b8:Size of containing directory, b7-b0: Chain status (valid when c_scl != 0) */
|
||||
DWORD c_ofs; /* Offset in the containing directory (valid when file object and sclust != 0) */
|
||||
#endif
|
||||
#if FF_FS_LOCK
|
||||
UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */
|
||||
UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */
|
||||
#endif
|
||||
} FFOBJID;
|
||||
|
||||
@@ -217,18 +202,18 @@ typedef struct {
|
||||
/* File object structure (FIL) */
|
||||
|
||||
typedef struct {
|
||||
FFOBJID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */
|
||||
BYTE flag; /* File status flags */
|
||||
BYTE err; /* Abort flag (error code) */
|
||||
FSIZE_t fptr; /* File read/write pointer (0 on open) */
|
||||
DWORD clust; /* Current cluster of fptr (invalid when fptr is 0) */
|
||||
LBA_t sect; /* Sector number appearing in buf[] (0:invalid) */
|
||||
FFOBJID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */
|
||||
BYTE flag; /* File status flags */
|
||||
BYTE err; /* Abort flag (error code) */
|
||||
FSIZE_t fptr; /* File read/write pointer (Zeroed on file open) */
|
||||
DWORD clust; /* Current cluster of fpter (invalid when fptr is 0) */
|
||||
LBA_t sect; /* Sector number appearing in buf[] (0:invalid) */
|
||||
#if !FF_FS_READONLY
|
||||
LBA_t dir_sect; /* Sector number containing the directory entry (not used in exFAT) */
|
||||
BYTE* dir_ptr; /* Pointer to the directory entry in the win[] (not used in exFAT) */
|
||||
LBA_t dir_sect; /* Sector number containing the directory entry (not used at exFAT) */
|
||||
BYTE* dir_ptr; /* Pointer to the directory entry in the win[] (not used at exFAT) */
|
||||
#endif
|
||||
#if FF_USE_FASTSEEK
|
||||
DWORD* cltbl; /* Pointer to the cluster link map table (nulled on open; set by application) */
|
||||
DWORD* cltbl; /* Pointer to the cluster link map table (nulled on open, set by application) */
|
||||
#endif
|
||||
#if !FF_FS_TINY
|
||||
BYTE buf[FF_MAX_SS]; /* File private data read/write window */
|
||||
@@ -240,44 +225,40 @@ typedef struct {
|
||||
/* Directory object structure (DIR) */
|
||||
|
||||
typedef struct {
|
||||
FFOBJID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */
|
||||
DWORD dptr; /* Current read/write offset */
|
||||
DWORD clust; /* Current cluster */
|
||||
LBA_t sect; /* Current sector (0:no more item to read) */
|
||||
BYTE* dir; /* Pointer to the directory item in the win[] in filesystem object */
|
||||
BYTE fn[12]; /* SFN (in/out) {body[0-7],ext[8-10],status[11]} */
|
||||
FFOBJID obj; /* Object identifier */
|
||||
DWORD dptr; /* Current read/write offset */
|
||||
DWORD clust; /* Current cluster */
|
||||
LBA_t sect; /* Current sector (0:Read operation has terminated) */
|
||||
BYTE* dir; /* Pointer to the directory item in the win[] */
|
||||
BYTE fn[12]; /* SFN (in/out) {body[8],ext[3],status[1]} */
|
||||
#if FF_USE_LFN
|
||||
DWORD blk_ofs; /* Offset of current entry block being processed (0xFFFFFFFF:invalid) */
|
||||
DWORD blk_ofs; /* Offset of current entry block being processed (0xFFFFFFFF:Invalid) */
|
||||
#endif
|
||||
#if FF_USE_FIND
|
||||
const TCHAR *pat; /* Pointer to the name matching pattern */
|
||||
const TCHAR* pat; /* Pointer to the name matching pattern */
|
||||
#endif
|
||||
} DIR;
|
||||
|
||||
|
||||
|
||||
/* File/directory information structure (FILINFO) */
|
||||
/* File information structure (FILINFO) */
|
||||
|
||||
typedef struct {
|
||||
FSIZE_t fsize; /* File size (invalid for directory) */
|
||||
WORD fdate; /* Date of file modification or directory creation */
|
||||
WORD ftime; /* Time of file modification or directory creation */
|
||||
#if FF_FS_CRTIME
|
||||
WORD crdate; /* Date of object createion */
|
||||
WORD crtime; /* Time of object createion */
|
||||
#endif
|
||||
BYTE fattrib; /* Object attribute */
|
||||
FSIZE_t fsize; /* File size */
|
||||
WORD fdate; /* Modified date */
|
||||
WORD ftime; /* Modified time */
|
||||
BYTE fattrib; /* File attribute */
|
||||
#if FF_USE_LFN
|
||||
TCHAR altname[FF_SFN_BUF + 1];/* Alternative object name */
|
||||
TCHAR fname[FF_LFN_BUF + 1]; /* Primary object name */
|
||||
TCHAR altname[FF_SFN_BUF + 1];/* Alternative file name */
|
||||
TCHAR fname[FF_LFN_BUF + 1]; /* Primary file name */
|
||||
#else
|
||||
TCHAR fname[12 + 1]; /* Object name */
|
||||
TCHAR fname[12 + 1]; /* File name */
|
||||
#endif
|
||||
} FILINFO;
|
||||
|
||||
|
||||
|
||||
/* Format parameter structure (MKFS_PARM) used for f_mkfs() */
|
||||
/* Format parameter structure (MKFS_PARM) */
|
||||
|
||||
typedef struct {
|
||||
BYTE fmt; /* Format option (FM_FAT, FM_FAT32, FM_EXFAT and FM_SFD) */
|
||||
@@ -292,24 +273,24 @@ typedef struct {
|
||||
/* File function return code (FRESULT) */
|
||||
|
||||
typedef enum {
|
||||
FR_OK = 0, /* (0) Function succeeded */
|
||||
FR_OK = 0, /* (0) Succeeded */
|
||||
FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */
|
||||
FR_INT_ERR, /* (2) Assertion failed */
|
||||
FR_NOT_READY, /* (3) The physical drive does not work */
|
||||
FR_NOT_READY, /* (3) The physical drive cannot work */
|
||||
FR_NO_FILE, /* (4) Could not find the file */
|
||||
FR_NO_PATH, /* (5) Could not find the path */
|
||||
FR_INVALID_NAME, /* (6) The path name format is invalid */
|
||||
FR_DENIED, /* (7) Access denied due to a prohibited access or directory full */
|
||||
FR_EXIST, /* (8) Access denied due to a prohibited access */
|
||||
FR_DENIED, /* (7) Access denied due to prohibited access or directory full */
|
||||
FR_EXIST, /* (8) Access denied due to prohibited access */
|
||||
FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */
|
||||
FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */
|
||||
FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */
|
||||
FR_NOT_ENABLED, /* (12) The volume has no work area */
|
||||
FR_NO_FILESYSTEM, /* (13) Could not find a valid FAT volume */
|
||||
FR_MKFS_ABORTED, /* (14) The f_mkfs function aborted due to some problem */
|
||||
FR_TIMEOUT, /* (15) Could not take control of the volume within defined period */
|
||||
FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */
|
||||
FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any problem */
|
||||
FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */
|
||||
FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */
|
||||
FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated, given buffer size is insufficient or too deep path */
|
||||
FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */
|
||||
FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > FF_FS_LOCK */
|
||||
FR_INVALID_PARAMETER /* (19) Given parameter is invalid */
|
||||
} FRESULT;
|
||||
@@ -396,7 +377,7 @@ DWORD ff_wtoupper (DWORD uni); /* Unicode upper-case conversion */
|
||||
void* ff_memalloc (UINT msize); /* Allocate memory block */
|
||||
void ff_memfree (void* mblock); /* Free memory block */
|
||||
#endif
|
||||
#if FF_FS_REENTRANT /* Sync functions */
|
||||
#if FF_FS_REENTRANT /* Sync functions */
|
||||
int ff_mutex_create (int vol); /* Create a sync object */
|
||||
void ff_mutex_delete (int vol); /* Delete a sync object */
|
||||
int ff_mutex_take (int vol); /* Lock sync object */
|
||||
@@ -410,7 +391,7 @@ void ff_mutex_give (int vol); /* Unlock sync object */
|
||||
/* Flags and Offset Address */
|
||||
/*--------------------------------------------------------------*/
|
||||
|
||||
/* File access mode and open method flags (3rd argument of f_open function) */
|
||||
/* File access mode and open method flags (3rd argument of f_open) */
|
||||
#define FA_READ 0x01
|
||||
#define FA_WRITE 0x02
|
||||
#define FA_OPEN_EXISTING 0x00
|
||||
@@ -419,10 +400,10 @@ void ff_mutex_give (int vol); /* Unlock sync object */
|
||||
#define FA_OPEN_ALWAYS 0x10
|
||||
#define FA_OPEN_APPEND 0x30
|
||||
|
||||
/* Fast seek controls (2nd argument of f_lseek function) */
|
||||
/* Fast seek controls (2nd argument of f_lseek) */
|
||||
#define CREATE_LINKMAP ((FSIZE_t)0 - 1)
|
||||
|
||||
/* Format options (2nd argument of f_mkfs function) */
|
||||
/* Format options (2nd argument of f_mkfs) */
|
||||
#define FM_FAT 0x01
|
||||
#define FM_FAT32 0x02
|
||||
#define FM_EXFAT 0x04
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
/ Configurations of FatFs Module
|
||||
/---------------------------------------------------------------------------*/
|
||||
|
||||
#define FFCONF_DEF 80386 /* Revision ID */
|
||||
#define FFCONF_DEF 80286 /* Revision ID */
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ Function Configurations
|
||||
@@ -31,36 +31,36 @@
|
||||
|
||||
|
||||
#define FF_USE_MKFS 1
|
||||
/* This option switches f_mkfs(). (0:Disable or 1:Enable) */
|
||||
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
|
||||
|
||||
|
||||
#define FF_USE_FASTSEEK 1
|
||||
/* This option switches fast seek feature. (0:Disable or 1:Enable) */
|
||||
/* This option switches fast seek function. (0:Disable or 1:Enable) */
|
||||
|
||||
|
||||
#define FF_USE_EXPAND 0
|
||||
/* This option switches f_expand(). (0:Disable or 1:Enable) */
|
||||
/* This option switches f_expand function. (0:Disable or 1:Enable) */
|
||||
|
||||
|
||||
#define FF_USE_CHMOD 0
|
||||
/* This option switches attribute control API functions, f_chmod() and f_utime().
|
||||
/* This option switches attribute manipulation functions, f_chmod() and f_utime().
|
||||
/ (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */
|
||||
|
||||
|
||||
#define FF_USE_LABEL 0
|
||||
/* This option switches volume label API functions, f_getlabel() and f_setlabel().
|
||||
/* This option switches volume label functions, f_getlabel() and f_setlabel().
|
||||
/ (0:Disable or 1:Enable) */
|
||||
|
||||
|
||||
#define FF_USE_FORWARD 0
|
||||
/* This option switches f_forward(). (0:Disable or 1:Enable) */
|
||||
/* This option switches f_forward() function. (0:Disable or 1:Enable) */
|
||||
|
||||
|
||||
#define FF_USE_STRFUNC 0
|
||||
#define FF_PRINT_LLI 0
|
||||
#define FF_PRINT_FLOAT 0
|
||||
#define FF_STRF_ENCODE 3
|
||||
/* FF_USE_STRFUNC switches string API functions, f_gets(), f_putc(), f_puts() and
|
||||
/* FF_USE_STRFUNC switches string functions, f_gets(), f_putc(), f_puts() and
|
||||
/ f_printf().
|
||||
/
|
||||
/ 0: Disable. FF_PRINT_LLI, FF_PRINT_FLOAT and FF_STRF_ENCODE have no effect.
|
||||
@@ -69,7 +69,7 @@
|
||||
/
|
||||
/ FF_PRINT_LLI = 1 makes f_printf() support long long argument and FF_PRINT_FLOAT = 1/2
|
||||
/ makes f_printf() support floating point argument. These features want C99 or later.
|
||||
/ When FF_LFN_UNICODE >= 1 with LFN enabled, string API functions convert the character
|
||||
/ When FF_LFN_UNICODE >= 1 with LFN enabled, string functions convert the character
|
||||
/ encoding in it. FF_STRF_ENCODE selects assumption of character encoding ON THE FILE
|
||||
/ to be read/written via those functions.
|
||||
/
|
||||
@@ -127,15 +127,15 @@
|
||||
/* 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.
|
||||
/ 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 feature
|
||||
/ 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 the LFN
|
||||
/ be in range of 12 to 255. It is recommended to be set it 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
|
||||
@@ -176,26 +176,14 @@
|
||||
|
||||
|
||||
#define FF_FS_RPATH 0
|
||||
/* This option configures support for relative path feature.
|
||||
/* This option configures support for relative path.
|
||||
/
|
||||
/ 0: Disable relative path and remove related API functions.
|
||||
/ 1: Enable relative path and dot names. f_chdir() and f_chdrive() are available.
|
||||
/ 2: f_getcwd() is available in addition to 1.
|
||||
/ 0: Disable relative path and remove related functions.
|
||||
/ 1: Enable relative path. f_chdir() and f_chdrive() are available.
|
||||
/ 2: f_getcwd() function is available in addition to 1.
|
||||
*/
|
||||
|
||||
|
||||
#define FF_PATH_DEPTH 10
|
||||
/* This option defines maximum depth of directory in the exFAT volume. It is NOT
|
||||
/ relevant to FAT/FAT32 volume.
|
||||
/ For example, FF_PATH_DEPTH = 3 will able to follow a path "/dir1/dir2/dir3/file"
|
||||
/ but a sub-directory in the dir3 will not able to be followed and set current
|
||||
/ directory.
|
||||
/ The size of filesystem object (FATFS) increases FF_PATH_DEPTH * 24 bytes.
|
||||
/ When FF_FS_EXFAT == 0 or FF_FS_RPATH == 0, this option has no effect.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ Drive/Volume Configurations
|
||||
/---------------------------------------------------------------------------*/
|
||||
@@ -213,7 +201,7 @@
|
||||
/* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings.
|
||||
/ When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive
|
||||
/ number in the path name. FF_VOLUME_STRS defines the volume ID strings for each
|
||||
/ logical drive. Number of items must not be less than FF_VOLUMES. Valid
|
||||
/ logical drives. Number of items must not be less than FF_VOLUMES. Valid
|
||||
/ characters for the volume ID strings are A-Z, a-z and 0-9, however, they are
|
||||
/ compared in case-insensitive. If FF_STR_VOLUME_ID >= 1 and FF_VOLUME_STRS is
|
||||
/ not defined, a user defined volume string table is needed as:
|
||||
@@ -226,9 +214,9 @@
|
||||
/* This option switches support for multiple volumes on the physical drive.
|
||||
/ By default (0), each logical drive number is bound to the same physical drive
|
||||
/ number and only an FAT volume found on the physical drive will be mounted.
|
||||
/ When this feature is enabled (1), each logical drive number can be bound to
|
||||
/ When this function is enabled (1), each logical drive number can be bound to
|
||||
/ arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk()
|
||||
/ will be available. */
|
||||
/ function will be available. */
|
||||
|
||||
|
||||
#define FF_MIN_SS 512
|
||||
@@ -240,8 +228,8 @@
|
||||
/* This set of options configures the range of sector size to be supported. (512,
|
||||
/ 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and
|
||||
/ harddisk, but a larger value may be required for on-board flash memory and some
|
||||
/ type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is
|
||||
/ configured for variable sector size mode and disk_ioctl() needs to implement
|
||||
/ type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is configured
|
||||
/ for variable sector size mode and disk_ioctl() function needs to implement
|
||||
/ GET_SECTOR_SIZE command. */
|
||||
|
||||
|
||||
@@ -251,14 +239,14 @@
|
||||
|
||||
|
||||
#define FF_MIN_GPT 0x10000000
|
||||
/* Minimum number of sectors to switch GPT as partitioning format in f_mkfs() and
|
||||
/ f_fdisk(). 2^32 sectors maximum. This option has no effect when FF_LBA64 == 0. */
|
||||
/* Minimum number of sectors to switch GPT as partitioning format in f_mkfs and
|
||||
/ f_fdisk function. 0x100000000 max. This option has no effect when FF_LBA64 == 0. */
|
||||
|
||||
|
||||
#define FF_USE_TRIM 0
|
||||
/* This option switches support for ATA-TRIM. (0:Disable or 1:Enable)
|
||||
/ To enable this feature, also CTRL_TRIM command should be implemented to
|
||||
/ the disk_ioctl(). */
|
||||
/ To enable Trim function, also CTRL_TRIM command should be implemented to the
|
||||
/ disk_ioctl() function. */
|
||||
|
||||
|
||||
|
||||
@@ -268,7 +256,7 @@
|
||||
|
||||
#define FF_FS_TINY 0
|
||||
/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny)
|
||||
/ At the tiny configuration, size of file object (FIL) is reduced FF_MAX_SS bytes.
|
||||
/ At the tiny configuration, size of file object (FIL) is shrinked FF_MAX_SS bytes.
|
||||
/ Instead of private sector buffer eliminated from the file object, common sector
|
||||
/ buffer in the filesystem object (FATFS) is used for the file data transfer. */
|
||||
|
||||
@@ -285,25 +273,20 @@
|
||||
#define FF_FS_NORTC 0
|
||||
#define FF_NORTC_MON 1
|
||||
#define FF_NORTC_MDAY 1
|
||||
#define FF_NORTC_YEAR 2025
|
||||
#define FF_NORTC_YEAR 2022
|
||||
/* The option FF_FS_NORTC switches timestamp feature. If the system does not have
|
||||
/ an RTC or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable the
|
||||
/ timestamp feature. Every object modified by FatFs will have a fixed timestamp
|
||||
/ defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time.
|
||||
/ To enable timestamp function (FF_FS_NORTC = 0), get_fattime() need to be added
|
||||
/ to the project to read current time form real-time clock. FF_NORTC_MON,
|
||||
/ To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be
|
||||
/ added to the project to read current time form real-time clock. FF_NORTC_MON,
|
||||
/ FF_NORTC_MDAY and FF_NORTC_YEAR have no effect.
|
||||
/ These options have no effect in read-only configuration (FF_FS_READONLY = 1). */
|
||||
|
||||
|
||||
#define FF_FS_CRTIME 0
|
||||
/* This option enables(1)/disables(0) the timestamp of the file created. When
|
||||
/ set 1, the file created time is available in FILINFO structure. */
|
||||
|
||||
|
||||
#define FF_FS_NOFSINFO 0
|
||||
/* If you need to know the correct free space on the FAT32 volume, set bit 0 of
|
||||
/ this option, and f_getfree() on the first time after volume mount will force
|
||||
/* If you need to know correct free space on the FAT32 volume, set bit 0 of this
|
||||
/ option, and f_getfree() function at the first time after volume mount will force
|
||||
/ a full FAT scan. Bit 1 controls the use of last allocated cluster number.
|
||||
/
|
||||
/ bit0=0: Use free cluster count in the FSINFO if available.
|
||||
@@ -340,17 +323,17 @@
|
||||
/* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs
|
||||
/ module itself. Note that regardless of this option, file access to different
|
||||
/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs()
|
||||
/ and f_fdisk(), are always not re-entrant. Only file/directory access to
|
||||
/ the same volume is under control of this featuer.
|
||||
/ and f_fdisk() function, are always not re-entrant. Only file/directory access
|
||||
/ to the same volume is under control of this featuer.
|
||||
/
|
||||
/ 0: Disable re-entrancy. FF_FS_TIMEOUT have no effect.
|
||||
/ 1: Enable re-entrancy. Also user provided synchronization handlers,
|
||||
/ ff_mutex_create(), ff_mutex_delete(), ff_mutex_take() and ff_mutex_give(),
|
||||
/ must be added to the project. Samples are available in ffsystem.c.
|
||||
/ ff_mutex_create(), ff_mutex_delete(), ff_mutex_take() and ff_mutex_give()
|
||||
/ function, must be added to the project. Samples are available in ffsystem.c.
|
||||
/
|
||||
/ The FF_FS_TIMEOUT defines timeout period in unit of O/S time tick.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*--- End of configuration options ---*/
|
||||
/*--- End of configuration options ---*/
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,56 +0,0 @@
|
||||
menuconfig RT_USING_VBUS
|
||||
bool "VBus: virtual software bus"
|
||||
default n
|
||||
|
||||
if RT_USING_VBUS
|
||||
config RT_USING_VBUS_RFS
|
||||
bool "Enable Remote File System on VBus"
|
||||
default n
|
||||
help
|
||||
When enable remote file system, the application can visit the remote file system
|
||||
through VBus with POSIX file I/O.
|
||||
|
||||
config RT_USING_VBUS_RSHELL
|
||||
bool "Enable Remote Shell on VBus"
|
||||
default n
|
||||
help
|
||||
When enable remote shell, the finsh/msh of RT-Thread can be operated from another
|
||||
Operating System.
|
||||
|
||||
config RT_VBUS_USING_TESTS
|
||||
bool "Enable tests on VBus"
|
||||
default n
|
||||
|
||||
config _RT_VBUS_RING_BASE
|
||||
hex "VBus address"
|
||||
help
|
||||
VBus ring buffer physical address.
|
||||
|
||||
config _RT_VBUS_RING_SZ
|
||||
int "VBus ring size"
|
||||
help
|
||||
VBus size of the ring buffer.
|
||||
|
||||
config RT_VBUS_GUEST_VIRQ
|
||||
int "RT_VBUS_GUEST_VIRQ"
|
||||
help
|
||||
The interrupt number used to notify the client on a particular system.
|
||||
|
||||
config RT_VBUS_HOST_VIRQ
|
||||
int "RT_VBUS_HOST_VIRQ"
|
||||
help
|
||||
The interrupt be triggered on a particular system when the client notify the host.
|
||||
|
||||
config RT_VBUS_SHELL_DEV_NAME
|
||||
string "RT_VBUS_SHELL_DEV_NAME"
|
||||
default "vbser0"
|
||||
help
|
||||
The name of the UBUS shell device.
|
||||
|
||||
config RT_VBUS_RFS_DEV_NAME
|
||||
string "RT_VBUS_RFS_DEV_NAME"
|
||||
default "rfs"
|
||||
help
|
||||
The name of the UBUS rfs device.
|
||||
|
||||
endif
|
||||
@@ -1,23 +0,0 @@
|
||||
# RT-Thread building script for component
|
||||
|
||||
import SCons, os
|
||||
from building import *
|
||||
|
||||
group = []
|
||||
if not GetDepend(['RT_USING_VBUS']):
|
||||
Return('group')
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
src = Glob('*.c')
|
||||
|
||||
for c, f in [['RT_USING_VBUS_RFS', 'utilities/rfs.c'],
|
||||
['RT_USING_VBUS_RSHELL', 'utilities/rshell.c'],
|
||||
]:
|
||||
if GetDepend(c):
|
||||
src += Glob(f)
|
||||
|
||||
CPPPATH = [cwd, os.path.join(cwd, 'share_hdr')]
|
||||
|
||||
group = DefineGroup('VBus', src, depend = ['RT_USING_VBUS'], CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
||||
@@ -1,256 +0,0 @@
|
||||
/*
|
||||
* COPYRIGHT (C) 2011-2021, Real-Thread Information Technology Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2013-11-04 Grissiom add comment
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
|
||||
#include "prio_queue.h"
|
||||
|
||||
struct rt_prio_queue_item {
|
||||
struct rt_prio_queue_item *next;
|
||||
/* data follows */
|
||||
};
|
||||
|
||||
static void _do_push(struct rt_prio_queue *que,
|
||||
rt_uint8_t prio,
|
||||
struct rt_prio_queue_item *item)
|
||||
{
|
||||
if (que->head[prio] == RT_NULL)
|
||||
{
|
||||
que->head[prio] = item;
|
||||
que->bitmap |= 1 << prio;
|
||||
}
|
||||
else
|
||||
{
|
||||
RT_ASSERT(que->tail[prio]);
|
||||
que->tail[prio]->next = item;
|
||||
}
|
||||
que->tail[prio] = item;
|
||||
}
|
||||
|
||||
static struct rt_prio_queue_item* _do_pop(struct rt_prio_queue *que)
|
||||
{
|
||||
int ffs;
|
||||
struct rt_prio_queue_item *item;
|
||||
|
||||
ffs = __rt_ffs(que->bitmap);
|
||||
if (ffs == 0)
|
||||
return RT_NULL;
|
||||
ffs--;
|
||||
|
||||
item = que->head[ffs];
|
||||
RT_ASSERT(item);
|
||||
|
||||
que->head[ffs] = item->next;
|
||||
if (que->head[ffs] == RT_NULL)
|
||||
{
|
||||
que->bitmap &= ~(1 << ffs);
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
rt_err_t rt_prio_queue_init(struct rt_prio_queue *que,
|
||||
const char *name,
|
||||
void *buf,
|
||||
rt_size_t bufsz,
|
||||
rt_size_t itemsz)
|
||||
{
|
||||
RT_ASSERT(que);
|
||||
|
||||
rt_memset(que, 0, sizeof(*que));
|
||||
|
||||
rt_list_init(&(que->suspended_pop_list));
|
||||
|
||||
rt_mp_init(&que->pool, name, buf, bufsz,
|
||||
sizeof(struct rt_prio_queue_item) + itemsz);
|
||||
|
||||
que->item_sz = itemsz;
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
void rt_prio_queue_detach(struct rt_prio_queue *que)
|
||||
{
|
||||
/* wake up all suspended pop threads, push thread is suspended on mempool.
|
||||
*/
|
||||
while (!rt_list_isempty(&(que->suspended_pop_list)))
|
||||
{
|
||||
rt_thread_t thread;
|
||||
|
||||
/* disable interrupt */
|
||||
rt_base_t level = rt_hw_interrupt_disable();
|
||||
|
||||
/* get next suspend thread */
|
||||
thread = RT_THREAD_LIST_NODE_ENTRY(que->suspended_pop_list.next);
|
||||
/* set error code to -RT_ERROR */
|
||||
thread->error = -RT_ERROR;
|
||||
|
||||
rt_thread_resume(thread);
|
||||
|
||||
/* enable interrupt */
|
||||
rt_hw_interrupt_enable(level);
|
||||
}
|
||||
rt_mp_detach(&que->pool);
|
||||
}
|
||||
|
||||
#ifdef RT_USING_HEAP
|
||||
struct rt_prio_queue* rt_prio_queue_create(const char *name,
|
||||
rt_size_t item_nr,
|
||||
rt_size_t item_sz)
|
||||
{
|
||||
struct rt_prio_queue *que;
|
||||
rt_size_t bufsz;
|
||||
|
||||
bufsz = item_nr * (sizeof(struct rt_prio_queue_item)
|
||||
+ item_sz
|
||||
+ sizeof(void*));
|
||||
|
||||
RT_ASSERT(item_nr);
|
||||
|
||||
que = rt_malloc(sizeof(*que) + bufsz);
|
||||
if (!que)
|
||||
return RT_NULL;
|
||||
|
||||
rt_prio_queue_init(que, name, que+1, bufsz, item_sz);
|
||||
|
||||
return que;
|
||||
}
|
||||
|
||||
void rt_prio_queue_delete(struct rt_prio_queue *que)
|
||||
{
|
||||
rt_prio_queue_detach(que);
|
||||
rt_free(que);
|
||||
}
|
||||
#endif
|
||||
|
||||
rt_err_t rt_prio_queue_push(struct rt_prio_queue *que,
|
||||
rt_uint8_t prio,
|
||||
void *data,
|
||||
rt_int32_t timeout)
|
||||
{
|
||||
rt_base_t level;
|
||||
struct rt_prio_queue_item *item;
|
||||
|
||||
RT_ASSERT(que);
|
||||
|
||||
if (prio >= RT_PRIO_QUEUE_PRIO_MAX)
|
||||
return -RT_ERROR;
|
||||
|
||||
item = rt_mp_alloc(&que->pool, timeout);
|
||||
if (item == RT_NULL)
|
||||
return -RT_ENOMEM;
|
||||
|
||||
rt_memcpy(item+1, data, que->item_sz);
|
||||
item->next = RT_NULL;
|
||||
|
||||
level = rt_hw_interrupt_disable();
|
||||
|
||||
_do_push(que, prio, item);
|
||||
|
||||
if (!rt_list_isempty(&(que->suspended_pop_list)))
|
||||
{
|
||||
rt_thread_t thread;
|
||||
|
||||
/* get thread entry */
|
||||
thread = RT_THREAD_LIST_NODE_ENTRY(que->suspended_pop_list.next);
|
||||
/* resume it */
|
||||
rt_thread_resume(thread);
|
||||
rt_hw_interrupt_enable(level);
|
||||
|
||||
/* perform a schedule */
|
||||
rt_schedule();
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
rt_hw_interrupt_enable(level);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
rt_err_t rt_prio_queue_pop(struct rt_prio_queue *que,
|
||||
void *data,
|
||||
rt_int32_t timeout)
|
||||
{
|
||||
rt_base_t level;
|
||||
struct rt_prio_queue_item *item;
|
||||
|
||||
RT_ASSERT(que);
|
||||
RT_ASSERT(data);
|
||||
|
||||
level = rt_hw_interrupt_disable();
|
||||
for (item = _do_pop(que);
|
||||
item == RT_NULL;
|
||||
item = _do_pop(que))
|
||||
{
|
||||
rt_thread_t thread;
|
||||
|
||||
if (timeout == 0)
|
||||
{
|
||||
rt_hw_interrupt_enable(level);
|
||||
return -RT_ETIMEOUT;
|
||||
}
|
||||
|
||||
RT_DEBUG_NOT_IN_INTERRUPT;
|
||||
|
||||
thread = rt_thread_self();
|
||||
thread->error = RT_EOK;
|
||||
rt_thread_suspend(thread);
|
||||
|
||||
rt_list_insert_before(&(que->suspended_pop_list), &RT_THREAD_LIST_NODE(thread));
|
||||
|
||||
if (timeout > 0)
|
||||
{
|
||||
rt_tick_t timeout_tick = timeout;
|
||||
rt_timer_control(&(thread->thread_timer),
|
||||
RT_TIMER_CTRL_SET_TIME,
|
||||
&timeout_tick);
|
||||
rt_timer_start(&(thread->thread_timer));
|
||||
}
|
||||
|
||||
rt_hw_interrupt_enable(level);
|
||||
|
||||
rt_schedule();
|
||||
|
||||
/* thread is waked up */
|
||||
if (thread->error != RT_EOK)
|
||||
return thread->error;
|
||||
level = rt_hw_interrupt_disable();
|
||||
}
|
||||
|
||||
rt_hw_interrupt_enable(level);
|
||||
|
||||
rt_memcpy(data, item+1, que->item_sz);
|
||||
rt_mp_free(item);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
void rt_prio_queue_dump(struct rt_prio_queue *que)
|
||||
{
|
||||
int level = 0;
|
||||
|
||||
rt_kprintf("bitmap: %08x\n", que->bitmap);
|
||||
for (level = 0; level < RT_PRIO_QUEUE_PRIO_MAX; level++)
|
||||
{
|
||||
struct rt_prio_queue_item *item;
|
||||
|
||||
rt_kprintf("%2d: ", level);
|
||||
for (item = que->head[level];
|
||||
item;
|
||||
item = item->next)
|
||||
{
|
||||
rt_kprintf("%p, ", item);
|
||||
}
|
||||
rt_kprintf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* COPYRIGHT (C) 2011-2021, Real-Thread Information Technology Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2013-11-04 Grissiom add comment
|
||||
*/
|
||||
|
||||
#ifndef __PRIO_QUEUE_H__
|
||||
#define __PRIO_QUEUE_H__
|
||||
|
||||
#include <rtthread.h>
|
||||
|
||||
#define RT_PRIO_QUEUE_PRIO_MAX 32
|
||||
|
||||
struct rt_prio_queue_item;
|
||||
|
||||
struct rt_prio_queue {
|
||||
rt_uint32_t bitmap;
|
||||
struct rt_prio_queue_item *head[RT_PRIO_QUEUE_PRIO_MAX];
|
||||
struct rt_prio_queue_item *tail[RT_PRIO_QUEUE_PRIO_MAX];
|
||||
/* push thread suspend on the mempool, not queue */
|
||||
rt_list_t suspended_pop_list;
|
||||
rt_size_t item_sz;
|
||||
|
||||
struct rt_mempool pool;
|
||||
};
|
||||
|
||||
rt_err_t rt_prio_queue_init(struct rt_prio_queue *que,
|
||||
const char *name,
|
||||
void *buf,
|
||||
rt_size_t bufsz,
|
||||
rt_size_t itemsz);
|
||||
void rt_prio_queue_detach(struct rt_prio_queue *que);
|
||||
|
||||
rt_err_t rt_prio_queue_push(struct rt_prio_queue *que,
|
||||
rt_uint8_t prio,
|
||||
void *data,
|
||||
rt_int32_t timeout);
|
||||
rt_err_t rt_prio_queue_pop(struct rt_prio_queue *que,
|
||||
void *data,
|
||||
rt_int32_t timeout);
|
||||
#ifdef RT_USING_HEAP
|
||||
struct rt_prio_queue* rt_prio_queue_create(const char *name,
|
||||
rt_size_t item_nr,
|
||||
rt_size_t item_sz);
|
||||
void rt_prio_queue_delete(struct rt_prio_queue *que);
|
||||
#endif
|
||||
|
||||
void rt_prio_queue_dump(struct rt_prio_queue *que);
|
||||
|
||||
#endif /* end of include guard: __PRIO_QUEUE_H__ */
|
||||
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
*/
|
||||
#ifndef __VBUS_API_H__
|
||||
#define __VBUS_API_H__
|
||||
|
||||
#define RT_VBUS_USING_FLOW_CONTROL
|
||||
|
||||
#define RT_VBUS_CHANNEL_NR 32
|
||||
|
||||
#define RT_VBUS_BLK_HEAD_SZ 4
|
||||
#define RT_VBUS_MAX_PKT_SZ (256 - RT_VBUS_BLK_HEAD_SZ)
|
||||
|
||||
#define RT_VMM_RB_BLK_NR (_RT_VBUS_RING_SZ / 64 - 1)
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#include <stddef.h> /* For size_t */
|
||||
|
||||
struct rt_vbus_blk
|
||||
{
|
||||
unsigned char id;
|
||||
unsigned char qos;
|
||||
unsigned char len;
|
||||
unsigned char reserved;
|
||||
unsigned char data[60];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct rt_vbus_ring
|
||||
{
|
||||
volatile size_t put_idx;
|
||||
volatile size_t get_idx;
|
||||
/* whether the writer is blocked on this ring. For RTT, it means the
|
||||
* central writer thread is waiting. For Linux, it means there are some
|
||||
* threads waiting for space to write.
|
||||
*
|
||||
* Note that we don't record whether there are reading thread blocked. When
|
||||
* there is new data, the other side will always be waked up. */
|
||||
volatile unsigned int blocked;
|
||||
struct rt_vbus_blk blks[RT_VMM_RB_BLK_NR];
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
RT_VBUS_CHN0_CMD_ENABLE,
|
||||
RT_VBUS_CHN0_CMD_DISABLE,
|
||||
RT_VBUS_CHN0_CMD_SET,
|
||||
RT_VBUS_CHN0_CMD_ACK,
|
||||
RT_VBUS_CHN0_CMD_NAK,
|
||||
/* If the recieving side reached high water mark. It has the right to
|
||||
* suspend the channel. All the server/client should know about this
|
||||
* command but the one that does not implement flow control could ignore
|
||||
* this command. */
|
||||
RT_VBUS_CHN0_CMD_SUSPEND,
|
||||
RT_VBUS_CHN0_CMD_RESUME,
|
||||
RT_VBUS_CHN0_CMD_MAX,
|
||||
};
|
||||
|
||||
enum rt_vbus_chn_status
|
||||
{
|
||||
/* initial state, available for reuse */
|
||||
RT_VBUS_CHN_ST_AVAILABLE,
|
||||
/* ACK DISABLE send(CS) or received(CS), but not ready for reuse.(the
|
||||
* channel is not closed by this end) */
|
||||
RT_VBUS_CHN_ST_CLOSED,
|
||||
/* ENABLE send(client) or received(server) */
|
||||
RT_VBUS_CHN_ST_ESTABLISHING,
|
||||
/* ACK SET send(C) or received(S) */
|
||||
RT_VBUS_CHN_ST_ESTABLISHED,
|
||||
/* Channel suspended by flow control. */
|
||||
RT_VBUS_CHN_ST_SUSPEND,
|
||||
/* DISABLE received(CS) */
|
||||
RT_VBUS_CHN_ST_CLOSING,
|
||||
};
|
||||
#endif
|
||||
|
||||
#undef BUILD_ASSERT
|
||||
/* borrowed from http://lxr.linux.no/linux+v2.6.26.5/include/linux/kernel.h#L494 */
|
||||
#define BUILD_ASSERT(condition) ((void)sizeof(char[1 - 2*!(condition)]))
|
||||
|
||||
/* max length of a channel name, including the \0 */
|
||||
#define RT_VBUS_CHN_NAME_MAX 16
|
||||
|
||||
#endif /* end of include guard: __VBUS_API_H__ */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,177 +0,0 @@
|
||||
/*
|
||||
* COPYRIGHT (C) 2011-2021, Real-Thread Information Technology Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2014-06-09 Grissiom version 2.0.2; add comment
|
||||
* 2015-01-06 Grissiom version 2.0.3; API change, no functional changes
|
||||
*/
|
||||
#ifndef __VBUS_H__
|
||||
#define __VBUS_H__
|
||||
|
||||
#include <vbus_api.h>
|
||||
|
||||
int rt_vbus_init(void *outr, void *inr);
|
||||
|
||||
void rt_vbus_resume_out_thread(void);
|
||||
|
||||
/** Post data on channel.
|
||||
*
|
||||
* @param chnr the channel number
|
||||
* @param prio the priority of the data
|
||||
* @param datap pointer to the actual data
|
||||
* @param size number of byte of the data
|
||||
* @param timeout the value used in the blocking API
|
||||
*
|
||||
* Note: rt_vbus_post is an asynchronous function that when it returns, the
|
||||
* @datap and @size is recorded in the post queue at least but there is no
|
||||
* guarantee that the data is copied into the ring buffer. To avoid data
|
||||
* corruption, you need to wait on the RT_VBUS_EVENT_ID_TX event.
|
||||
*
|
||||
* However, if you just post static data such as static string, there is no
|
||||
* need to wait.
|
||||
*
|
||||
* @sa rt_vbus_register_listener .
|
||||
*/
|
||||
rt_err_t rt_vbus_post(rt_uint8_t chnr,
|
||||
rt_uint8_t prio,
|
||||
const void *datap,
|
||||
rt_size_t size,
|
||||
rt_int32_t timeout);
|
||||
|
||||
struct rt_vbus_data {
|
||||
/* Number of bytes in current data package. */
|
||||
unsigned char size;
|
||||
/* Used internally in VBus. Don't modify this field as it may corrupt the
|
||||
* receive queue. */
|
||||
struct rt_vbus_data *next;
|
||||
/* Data follows the struct */
|
||||
};
|
||||
|
||||
struct rt_vbus_wm_cfg {
|
||||
unsigned int low, high;
|
||||
};
|
||||
|
||||
struct rt_vbus_request {
|
||||
unsigned char prio;
|
||||
const char *name;
|
||||
int is_server;
|
||||
struct rt_vbus_wm_cfg recv_wm, post_wm;
|
||||
};
|
||||
|
||||
/** Request a channel.
|
||||
*
|
||||
* @return channel number. Negative if error happened.
|
||||
*/
|
||||
int rt_vbus_request_chn(struct rt_vbus_request *req, int timeout);
|
||||
|
||||
/** Close channel @chnr */
|
||||
void rt_vbus_close_chn(unsigned char chnr);
|
||||
|
||||
/** Set the water mark level for posting into the channel @chnr. */
|
||||
void rt_vbus_set_post_wm(unsigned char chnr, unsigned int low, unsigned int high);
|
||||
/** Set the water mark level for receiving from the channel @chnr. */
|
||||
void rt_vbus_set_recv_wm(unsigned char chnr, unsigned int low, unsigned int high);
|
||||
|
||||
typedef void (*rt_vbus_event_listener)(void *ctx);
|
||||
|
||||
enum rt_vbus_event_id {
|
||||
/* On a packet received in channel. */
|
||||
RT_VBUS_EVENT_ID_RX,
|
||||
/* On the data of rt_vbus_post has been written to the ring buffer. */
|
||||
RT_VBUS_EVENT_ID_TX,
|
||||
/* On the channel has been closed. */
|
||||
RT_VBUS_EVENT_ID_DISCONN,
|
||||
RT_VBUS_EVENT_ID_MAX,
|
||||
};
|
||||
|
||||
/** Register callback @indi on the event @eve on the @chnr.
|
||||
*
|
||||
* @ctx will passed to @indi on calling the @indi.
|
||||
*/
|
||||
void rt_vbus_register_listener(unsigned char chnr,
|
||||
enum rt_vbus_event_id eve,
|
||||
rt_vbus_event_listener indi,
|
||||
void *ctx);
|
||||
|
||||
/** Listen on any events happen on the @chnr for @timeout ticks.
|
||||
*
|
||||
* This function blocks until events occur or timeout happened.
|
||||
*/
|
||||
rt_err_t rt_vbus_listen_on(rt_uint8_t chnr,
|
||||
rt_int32_t timeout);
|
||||
|
||||
/** Push a data package into the receive queue of the channel @chnr. */
|
||||
void rt_vbus_data_push(unsigned int chnr,
|
||||
struct rt_vbus_data *data);
|
||||
/** Pop a data package from the receive queue of the channel @chnr.
|
||||
*
|
||||
* The actual data is following the struct rt_vbus_data. After using it, it
|
||||
* should be freed by rt_free.
|
||||
*/
|
||||
struct rt_vbus_data* rt_vbus_data_pop(unsigned int chnr);
|
||||
|
||||
struct rt_vbus_dev
|
||||
{
|
||||
/* Runtime infomations. */
|
||||
rt_uint8_t chnr;
|
||||
struct rt_vbus_data *act;
|
||||
rt_size_t pos;
|
||||
|
||||
/* There will be a request for each channel. So no need to seperate them so
|
||||
* clearly. */
|
||||
struct rt_vbus_request req;
|
||||
};
|
||||
|
||||
rt_err_t rt_vbus_chnx_init(void);
|
||||
/** Get the corresponding channel number from the VBus device @dev. */
|
||||
rt_uint8_t rt_vbus_get_chnnr(rt_device_t dev);
|
||||
/** Register a call back on the other side disconnect the channel.
|
||||
*
|
||||
* @sa rt_vbus_register_listener .
|
||||
*/
|
||||
void rt_vbus_chnx_register_disconn(rt_device_t dev,
|
||||
rt_vbus_event_listener indi,
|
||||
void *ctx);
|
||||
|
||||
/* Commands for the device control interface. */
|
||||
#define VBUS_IOCRECV_WM 0xD1
|
||||
#define VBUS_IOCPOST_WM 0xD2
|
||||
/** Configure event listener */
|
||||
#define VBUS_IOC_LISCFG 0xD3
|
||||
|
||||
struct rt_vbus_dev_liscfg
|
||||
{
|
||||
enum rt_vbus_event_id event;
|
||||
rt_vbus_event_listener listener;
|
||||
void *ctx;
|
||||
};
|
||||
|
||||
int rt_vbus_shell_start(void);
|
||||
#ifdef RT_USING_VBUS_RFS
|
||||
int dfs_rfs_init(void);
|
||||
#endif
|
||||
|
||||
/** VBus hardware init function.
|
||||
*
|
||||
* BSP should implement this function to initialize the interrupts etc.
|
||||
*/
|
||||
int rt_vbus_hw_init(void);
|
||||
|
||||
/** VBus ISR function.
|
||||
*
|
||||
* BSP should call this function when the interrupt from other core is
|
||||
* triggered. @param is not used by VBus and will pass to rt_vbus_hw_eoi.
|
||||
*/
|
||||
void rt_vbus_isr(int irqnr, void *param);
|
||||
|
||||
/** VBus End Of Interrupt function.
|
||||
*
|
||||
* This function will be called when VBus finished the ISR handling. BSP should
|
||||
* define this function to clear the interrupt flag etc.
|
||||
*/
|
||||
int rt_vbus_hw_eoi(int irqnr, void *param);
|
||||
|
||||
#endif /* end of include guard: __VBUS_H__ */
|
||||
@@ -1,269 +0,0 @@
|
||||
/*
|
||||
* COPYRIGHT (C) 2011-2021, Real-Thread Information Technology Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2013-11-04 Grissiom add comment
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
#include <rtdevice.h>
|
||||
|
||||
#include "vbus.h"
|
||||
|
||||
static void _rx_indicate(void *ctx)
|
||||
{
|
||||
rt_device_t dev = ctx;
|
||||
|
||||
if (dev->rx_indicate)
|
||||
dev->rx_indicate(dev, 0);
|
||||
}
|
||||
|
||||
static void _tx_complete(void *ctx)
|
||||
{
|
||||
rt_device_t dev = ctx;
|
||||
|
||||
if (dev->tx_complete)
|
||||
dev->tx_complete(dev, 0);
|
||||
}
|
||||
|
||||
static rt_err_t _open(rt_device_t dev, rt_uint16_t oflag)
|
||||
{
|
||||
int chnr;
|
||||
struct rt_vbus_dev *vdev = dev->user_data;
|
||||
|
||||
if (vdev->chnr)
|
||||
return RT_EOK;
|
||||
|
||||
/* FIXME: request the same name for twice will crash */
|
||||
chnr = rt_vbus_request_chn(&vdev->req, RT_WAITING_FOREVER);
|
||||
if (chnr < 0)
|
||||
return chnr;
|
||||
|
||||
vdev->chnr = chnr;
|
||||
rt_vbus_register_listener(chnr, RT_VBUS_EVENT_ID_RX, _rx_indicate, dev);
|
||||
rt_vbus_register_listener(chnr, RT_VBUS_EVENT_ID_TX, _tx_complete, dev);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t _close(rt_device_t dev)
|
||||
{
|
||||
struct rt_vbus_dev *vdev = dev->user_data;
|
||||
|
||||
RT_ASSERT(vdev->chnr != 0);
|
||||
|
||||
rt_vbus_close_chn(vdev->chnr);
|
||||
vdev->chnr = 0;
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_ssize_t _read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
|
||||
{
|
||||
rt_size_t outsz = 0;
|
||||
struct rt_vbus_dev *vdev = dev->user_data;
|
||||
|
||||
RT_ASSERT(vdev->chnr != 0);
|
||||
|
||||
if (vdev->act == RT_NULL)
|
||||
{
|
||||
vdev->act = rt_vbus_data_pop(vdev->chnr);
|
||||
vdev->pos = 0;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
rt_err_t err;
|
||||
|
||||
while (vdev->act)
|
||||
{
|
||||
rt_size_t cpysz;
|
||||
|
||||
if (size - outsz > vdev->act->size - vdev->pos)
|
||||
cpysz = vdev->act->size - vdev->pos;
|
||||
else
|
||||
cpysz = size - outsz;
|
||||
|
||||
rt_memcpy((char*)buffer + outsz, ((char*)(vdev->act+1)) + vdev->pos, cpysz);
|
||||
vdev->pos += cpysz;
|
||||
|
||||
outsz += cpysz;
|
||||
if (outsz == size)
|
||||
{
|
||||
return outsz;
|
||||
}
|
||||
else if (outsz > size)
|
||||
RT_ASSERT(0);
|
||||
|
||||
/* free old and get new */
|
||||
rt_free(vdev->act);
|
||||
vdev->act = rt_vbus_data_pop(vdev->chnr);
|
||||
vdev->pos = 0;
|
||||
}
|
||||
|
||||
/* TODO: We don't want to touch the rx_indicate here. But this lead to
|
||||
* some duplication. Maybe we should find a better way to handle this.
|
||||
*/
|
||||
if (rt_interrupt_get_nest() == 0)
|
||||
{
|
||||
err = rt_vbus_listen_on(vdev->chnr, RT_WAITING_FOREVER);
|
||||
}
|
||||
else
|
||||
{
|
||||
err = rt_vbus_listen_on(vdev->chnr, 0);
|
||||
}
|
||||
if (err != RT_EOK)
|
||||
{
|
||||
rt_set_errno(err);
|
||||
return outsz;
|
||||
}
|
||||
vdev->act = rt_vbus_data_pop(vdev->chnr);
|
||||
vdev->pos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static rt_ssize_t _write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
|
||||
{
|
||||
rt_err_t err;
|
||||
struct rt_vbus_dev *vdev = dev->user_data;
|
||||
|
||||
RT_ASSERT(vdev->chnr != 0);
|
||||
|
||||
if (rt_interrupt_get_nest() == 0)
|
||||
{
|
||||
/* Thread context. */
|
||||
err = rt_vbus_post(vdev->chnr, vdev->req.prio,
|
||||
buffer, size, RT_WAITING_FOREVER);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Interrupt context. */
|
||||
err = rt_vbus_post(vdev->chnr, vdev->req.prio,
|
||||
buffer, size, 0);
|
||||
}
|
||||
|
||||
if (err)
|
||||
{
|
||||
rt_set_errno(err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
rt_err_t _control(rt_device_t dev, int cmd, void *args)
|
||||
{
|
||||
RT_ASSERT(dev);
|
||||
|
||||
switch (cmd) {
|
||||
case VBUS_IOC_LISCFG: {
|
||||
struct rt_vbus_dev *vdev = dev->user_data;
|
||||
struct rt_vbus_dev_liscfg *liscfg = args;
|
||||
|
||||
RT_ASSERT(vdev->chnr != 0);
|
||||
if (!liscfg)
|
||||
return -RT_ERROR;
|
||||
|
||||
rt_vbus_register_listener(vdev->chnr, liscfg->event,
|
||||
liscfg->listener, liscfg->ctx);
|
||||
return RT_EOK;
|
||||
}
|
||||
break;
|
||||
#ifdef RT_VBUS_USING_FLOW_CONTROL
|
||||
case VBUS_IOCRECV_WM: {
|
||||
struct rt_vbus_dev *vdev = dev->user_data;
|
||||
struct rt_vbus_wm_cfg *cfg;
|
||||
|
||||
RT_ASSERT(vdev->chnr != 0);
|
||||
|
||||
if (!args)
|
||||
return -RT_ERROR;
|
||||
|
||||
cfg = (struct rt_vbus_wm_cfg*)args;
|
||||
if (cfg->low > cfg->high)
|
||||
return -RT_ERROR;
|
||||
|
||||
rt_vbus_set_recv_wm(vdev->chnr, cfg->low, cfg->high);
|
||||
return RT_EOK;
|
||||
}
|
||||
break;
|
||||
case VBUS_IOCPOST_WM: {
|
||||
struct rt_vbus_dev *vdev = dev->user_data;
|
||||
struct rt_vbus_wm_cfg *cfg;
|
||||
|
||||
RT_ASSERT(vdev->chnr != 0);
|
||||
|
||||
if (!args)
|
||||
return -RT_ERROR;
|
||||
|
||||
cfg = (struct rt_vbus_wm_cfg*)args;
|
||||
if (cfg->low > cfg->high)
|
||||
return -RT_ERROR;
|
||||
|
||||
rt_vbus_set_post_wm(vdev->chnr, cfg->low, cfg->high);
|
||||
return RT_EOK;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
return -RT_ENOSYS;
|
||||
}
|
||||
|
||||
rt_uint8_t rt_vbus_get_chnnr(rt_device_t dev)
|
||||
{
|
||||
struct rt_vbus_dev *vdev;
|
||||
|
||||
RT_ASSERT(dev);
|
||||
|
||||
vdev = dev->user_data;
|
||||
|
||||
return vdev->chnr;
|
||||
}
|
||||
|
||||
void rt_vbus_chnx_register_disconn(rt_device_t dev,
|
||||
rt_vbus_event_listener indi,
|
||||
void *ctx)
|
||||
{
|
||||
if (dev && dev->user_data)
|
||||
{
|
||||
struct rt_vbus_dev *vdev = dev->user_data;
|
||||
RT_ASSERT(vdev->chnr != 0);
|
||||
|
||||
rt_vbus_register_listener(vdev->chnr, RT_VBUS_EVENT_ID_DISCONN,
|
||||
indi, ctx);
|
||||
}
|
||||
}
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
|
||||
|
||||
extern struct rt_vbus_dev rt_vbus_chn_devx[];
|
||||
static struct rt_device _devx[32];
|
||||
|
||||
rt_err_t rt_vbus_chnx_init(void)
|
||||
{
|
||||
int i;
|
||||
struct rt_vbus_dev *p;
|
||||
|
||||
for (i = 0, p = rt_vbus_chn_devx;
|
||||
i < ARRAY_SIZE(_devx) && p->req.name;
|
||||
i++, p++)
|
||||
{
|
||||
_devx[i].type = RT_Device_Class_Char;
|
||||
_devx[i].open = _open;
|
||||
_devx[i].close = _close;
|
||||
_devx[i].read = _read;
|
||||
_devx[i].write = _write;
|
||||
_devx[i].control = _control;
|
||||
_devx[i].user_data = p;
|
||||
rt_device_register(&_devx[i], p->req.name, RT_DEVICE_FLAG_RDWR);
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* COPYRIGHT (C) 2011-2021, Real-Thread Information Technology Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2014-04-16 Grissiom first version
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
|
||||
#include "watermark_queue.h"
|
||||
|
||||
void rt_wm_que_set_mark(struct rt_watermark_queue *wg,
|
||||
unsigned int low, unsigned int high)
|
||||
{
|
||||
RT_ASSERT(low <= high);
|
||||
|
||||
wg->high_mark = high;
|
||||
wg->low_mark = low;
|
||||
}
|
||||
|
||||
void rt_wm_que_init(struct rt_watermark_queue *wg,
|
||||
unsigned int low, unsigned int high)
|
||||
{
|
||||
rt_wm_que_set_mark(wg, low, high);
|
||||
rt_list_init(&wg->suspended_threads);
|
||||
wg->level = 0;
|
||||
}
|
||||
|
||||
void rt_wm_que_dump(struct rt_watermark_queue *wg)
|
||||
{
|
||||
struct rt_list_node *node;
|
||||
|
||||
rt_kprintf("wg %p: low: %d, high: %d, cur: %d\n",
|
||||
wg, wg->low_mark, wg->high_mark, wg->level);
|
||||
rt_kprintf("thread suspend:");
|
||||
for (node = wg->suspended_threads.next;
|
||||
node != &wg->suspended_threads;
|
||||
node = node->next)
|
||||
{
|
||||
rt_thread_t thread;
|
||||
|
||||
thread = RT_THREAD_LIST_NODE_ENTRY(wg->suspended_threads.next);
|
||||
rt_kprintf(" %.*s", RT_NAME_MAX, thread->parent.name);
|
||||
}
|
||||
rt_kprintf("\n");
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
/*
|
||||
* COPYRIGHT (C) 2011-2021, Real-Thread Information Technology Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2014-04-16 Grissiom first version
|
||||
*/
|
||||
|
||||
struct rt_watermark_queue
|
||||
{
|
||||
/* Current water level. */
|
||||
unsigned int level;
|
||||
unsigned int high_mark;
|
||||
unsigned int low_mark;
|
||||
rt_list_t suspended_threads;
|
||||
};
|
||||
|
||||
/** Init the struct rt_watermark_queue.
|
||||
*/
|
||||
void rt_wm_que_init(struct rt_watermark_queue *wg,
|
||||
unsigned int low, unsigned int high);
|
||||
void rt_wm_que_set_mark(struct rt_watermark_queue *wg,
|
||||
unsigned int low, unsigned int high);
|
||||
void rt_wm_que_dump(struct rt_watermark_queue *wg);
|
||||
|
||||
/* Water marks are often used in performance critical places. Benchmark shows
|
||||
* inlining functions will have 10% performance gain in some situation(for
|
||||
* example, VBus). So keep the inc/dec compact and inline. */
|
||||
|
||||
/** Increase the water level.
|
||||
*
|
||||
* It should be called in the thread that want to raise the water level. If the
|
||||
* current level is above the high mark, the thread will be suspended up to
|
||||
* @timeout ticks.
|
||||
*
|
||||
* @return RT_EOK if water level increased successfully. -RT_EFULL on @timeout
|
||||
* is zero and the level is above water mark. -RT_ETIMEOUT if timeout occurred.
|
||||
*/
|
||||
rt_inline rt_err_t rt_wm_que_inc(struct rt_watermark_queue *wg,
|
||||
int timeout)
|
||||
{
|
||||
rt_base_t level;
|
||||
|
||||
/* Assert as early as possible. */
|
||||
if (timeout != 0)
|
||||
{
|
||||
RT_DEBUG_IN_THREAD_CONTEXT;
|
||||
}
|
||||
|
||||
level = rt_hw_interrupt_disable();
|
||||
|
||||
while (wg->level > wg->high_mark)
|
||||
{
|
||||
rt_thread_t thread;
|
||||
|
||||
if (timeout == 0)
|
||||
{
|
||||
rt_hw_interrupt_enable(level);
|
||||
return -RT_EFULL;
|
||||
}
|
||||
|
||||
thread = rt_thread_self();
|
||||
thread->error = RT_EOK;
|
||||
rt_thread_suspend(thread);
|
||||
rt_list_insert_after(&wg->suspended_threads, &RT_THREAD_LIST_NODE(thread));
|
||||
if (timeout > 0)
|
||||
{
|
||||
rt_tick_t timeout_tick = timeout;
|
||||
rt_timer_control(&(thread->thread_timer),
|
||||
RT_TIMER_CTRL_SET_TIME,
|
||||
&timeout_tick);
|
||||
rt_timer_start(&(thread->thread_timer));
|
||||
}
|
||||
rt_hw_interrupt_enable(level);
|
||||
rt_schedule();
|
||||
if (thread->error != RT_EOK)
|
||||
return thread->error;
|
||||
|
||||
level = rt_hw_interrupt_disable();
|
||||
}
|
||||
|
||||
wg->level++;
|
||||
|
||||
if (wg->level == 0)
|
||||
{
|
||||
wg->level = ~0;
|
||||
}
|
||||
|
||||
rt_hw_interrupt_enable(level);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
/** Decrease the water level.
|
||||
*
|
||||
* It should be called by the consumer that drain the water out. If the water
|
||||
* level reached low mark, all the thread suspended in this queue will be waken
|
||||
* up. It's safe to call this function in interrupt context.
|
||||
*/
|
||||
rt_inline void rt_wm_que_dec(struct rt_watermark_queue *wg)
|
||||
{
|
||||
int need_sched = 0;
|
||||
rt_base_t level;
|
||||
|
||||
if (wg->level == 0)
|
||||
return;
|
||||
|
||||
level = rt_hw_interrupt_disable();
|
||||
wg->level--;
|
||||
if (wg->level == wg->low_mark)
|
||||
{
|
||||
/* There should be spaces between the low mark and high mark, so it's
|
||||
* safe to resume all the threads. */
|
||||
while (!rt_list_isempty(&wg->suspended_threads))
|
||||
{
|
||||
rt_thread_t thread;
|
||||
|
||||
thread = RT_THREAD_LIST_NODE_ENTRY(wg->suspended_threads.next);
|
||||
rt_thread_resume(thread);
|
||||
need_sched = 1;
|
||||
}
|
||||
}
|
||||
rt_hw_interrupt_enable(level);
|
||||
|
||||
if (need_sched)
|
||||
rt_schedule();
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
# RT-Thread building script for component
|
||||
|
||||
from building import *
|
||||
|
||||
Import('rtconfig')
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
src = Glob('*.c') + Glob('*.cpp')
|
||||
CPPPATH = [cwd]
|
||||
|
||||
if rtconfig.PLATFORM in ['armcc', 'armclang']:
|
||||
src += Glob('*_rvds.S')
|
||||
|
||||
if rtconfig.PLATFORM in ['gcc']:
|
||||
src += Glob('*_init.S')
|
||||
src += Glob('*_gcc.S')
|
||||
|
||||
if rtconfig.PLATFORM in ['iccarm']:
|
||||
src += Glob('*_iar.S')
|
||||
|
||||
group = DefineGroup('libcpu', src, depend = [''], CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
||||
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
*/
|
||||
#ifndef __ARMV7_H__
|
||||
#define __ARMV7_H__
|
||||
|
||||
/* the exception stack without VFP registers */
|
||||
struct rt_hw_exp_stack
|
||||
{
|
||||
unsigned long r0;
|
||||
unsigned long r1;
|
||||
unsigned long r2;
|
||||
unsigned long r3;
|
||||
unsigned long r4;
|
||||
unsigned long r5;
|
||||
unsigned long r6;
|
||||
unsigned long r7;
|
||||
unsigned long r8;
|
||||
unsigned long r9;
|
||||
unsigned long r10;
|
||||
unsigned long fp;
|
||||
unsigned long ip;
|
||||
unsigned long sp;
|
||||
unsigned long lr;
|
||||
unsigned long pc;
|
||||
unsigned long cpsr;
|
||||
};
|
||||
|
||||
struct rt_hw_stack
|
||||
{
|
||||
unsigned long cpsr;
|
||||
unsigned long r0;
|
||||
unsigned long r1;
|
||||
unsigned long r2;
|
||||
unsigned long r3;
|
||||
unsigned long r4;
|
||||
unsigned long r5;
|
||||
unsigned long r6;
|
||||
unsigned long r7;
|
||||
unsigned long r8;
|
||||
unsigned long r9;
|
||||
unsigned long r10;
|
||||
unsigned long fp;
|
||||
unsigned long ip;
|
||||
unsigned long lr;
|
||||
unsigned long pc;
|
||||
};
|
||||
|
||||
#define USERMODE 0x10
|
||||
#define FIQMODE 0x11
|
||||
#define IRQMODE 0x12
|
||||
#define SVCMODE 0x13
|
||||
#define MONITORMODE 0x16
|
||||
#define ABORTMODE 0x17
|
||||
#define HYPMODE 0x1b
|
||||
#define UNDEFMODE 0x1b
|
||||
#define MODEMASK 0x1f
|
||||
#define NOINT 0xc0
|
||||
|
||||
#define T_Bit (1<<5)
|
||||
#define F_Bit (1<<6)
|
||||
#define I_Bit (1<<7)
|
||||
#define A_Bit (1<<8)
|
||||
#define E_Bit (1<<9)
|
||||
#define J_Bit (1<<24)
|
||||
|
||||
#endif
|
||||
@@ -1,93 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2013-07-05 Bernard the first version
|
||||
*/
|
||||
|
||||
#include <rtconfig.h>
|
||||
|
||||
.section .text, "ax"
|
||||
/*
|
||||
* rt_base_t rt_hw_interrupt_disable();
|
||||
*/
|
||||
.globl rt_hw_interrupt_disable
|
||||
rt_hw_interrupt_disable:
|
||||
mrs r0, cpsr
|
||||
cpsid i
|
||||
bx lr
|
||||
|
||||
/*
|
||||
* void rt_hw_interrupt_enable(rt_base_t level);
|
||||
*/
|
||||
.globl rt_hw_interrupt_enable
|
||||
rt_hw_interrupt_enable:
|
||||
msr cpsr, r0
|
||||
bx lr
|
||||
|
||||
/*
|
||||
* void rt_hw_context_switch_to(rt_uint32 to);
|
||||
* r0 --> to
|
||||
*/
|
||||
.globl rt_hw_context_switch_to
|
||||
rt_hw_context_switch_to:
|
||||
ldr sp, [r0] @ get new task stack pointer
|
||||
|
||||
ldmfd sp!, {r4} @ pop new task spsr
|
||||
msr spsr_cxsf, r4
|
||||
|
||||
ldmfd sp!, {r0-r12, lr, pc}^ @ pop new task r0-r12, lr & pc
|
||||
|
||||
.section .bss.share.isr
|
||||
_guest_switch_lvl:
|
||||
.word 0
|
||||
|
||||
.globl vmm_virq_update
|
||||
|
||||
.section .text.isr, "ax"
|
||||
/*
|
||||
* void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
|
||||
* r0 --> from
|
||||
* r1 --> to
|
||||
*/
|
||||
.globl rt_hw_context_switch
|
||||
rt_hw_context_switch:
|
||||
stmfd sp!, {lr} @ push pc (lr should be pushed in place of PC)
|
||||
stmfd sp!, {r0-r12, lr} @ push lr & register file
|
||||
|
||||
mrs r4, cpsr
|
||||
tst lr, #0x01
|
||||
orrne r4, r4, #0x20 @ it's thumb code
|
||||
|
||||
stmfd sp!, {r4} @ push cpsr
|
||||
|
||||
str sp, [r0] @ store sp in preempted tasks TCB
|
||||
ldr sp, [r1] @ get new task stack pointer
|
||||
|
||||
ldmfd sp!, {r4} @ pop new task cpsr to spsr
|
||||
msr spsr_cxsf, r4
|
||||
ldmfd sp!, {r0-r12, lr, pc}^ @ pop new task r0-r12, lr & pc, copy spsr to cpsr
|
||||
|
||||
/*
|
||||
* void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to);
|
||||
*/
|
||||
.globl rt_thread_switch_interrupt_flag
|
||||
.globl rt_interrupt_from_thread
|
||||
.globl rt_interrupt_to_thread
|
||||
.globl rt_hw_context_switch_interrupt
|
||||
rt_hw_context_switch_interrupt:
|
||||
ldr r2, =rt_thread_switch_interrupt_flag
|
||||
ldr r3, [r2]
|
||||
cmp r3, #1
|
||||
beq _reswitch
|
||||
ldr ip, =rt_interrupt_from_thread @ set rt_interrupt_from_thread
|
||||
mov r3, #1 @ set rt_thread_switch_interrupt_flag to 1
|
||||
str r0, [ip]
|
||||
str r3, [r2]
|
||||
_reswitch:
|
||||
ldr r2, =rt_interrupt_to_thread @ set rt_interrupt_to_thread
|
||||
str r1, [r2]
|
||||
bx lr
|
||||
@@ -1,20 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
*/
|
||||
#ifndef __CP15_H__
|
||||
#define __CP15_H__
|
||||
|
||||
unsigned long rt_cpu_get_smp_id(void);
|
||||
|
||||
void rt_cpu_mmu_disable(void);
|
||||
void rt_cpu_mmu_enable(void);
|
||||
void rt_cpu_tlb_set(volatile unsigned long*);
|
||||
|
||||
void rt_cpu_vector_set_base(unsigned int addr);
|
||||
|
||||
#endif
|
||||
@@ -1,125 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2013-07-05 Bernard the first version
|
||||
*/
|
||||
|
||||
.globl rt_cpu_get_smp_id
|
||||
rt_cpu_get_smp_id:
|
||||
mrc p15, #0, r0, c0, c0, #5
|
||||
bx lr
|
||||
|
||||
.globl rt_cpu_vector_set_base
|
||||
rt_cpu_vector_set_base:
|
||||
mcr p15, #0, r0, c12, c0, #0
|
||||
dsb
|
||||
bx lr
|
||||
|
||||
.globl rt_hw_cpu_dcache_enable
|
||||
rt_hw_cpu_dcache_enable:
|
||||
mrc p15, #0, r0, c1, c0, #0
|
||||
orr r0, r0, #0x00000004
|
||||
mcr p15, #0, r0, c1, c0, #0
|
||||
bx lr
|
||||
|
||||
.globl rt_hw_cpu_icache_enable
|
||||
rt_hw_cpu_icache_enable:
|
||||
mrc p15, #0, r0, c1, c0, #0
|
||||
orr r0, r0, #0x00001000
|
||||
mcr p15, #0, r0, c1, c0, #0
|
||||
bx lr
|
||||
|
||||
_FLD_MAX_WAY:
|
||||
.word 0x3ff
|
||||
_FLD_MAX_IDX:
|
||||
.word 0x7ff
|
||||
|
||||
.globl rt_cpu_dcache_clean_flush
|
||||
rt_cpu_dcache_clean_flush:
|
||||
push {r4-r11}
|
||||
dmb
|
||||
mrc p15, #1, r0, c0, c0, #1 @ read clid register
|
||||
ands r3, r0, #0x7000000 @ get level of coherency
|
||||
mov r3, r3, lsr #23
|
||||
beq finished
|
||||
mov r10, #0
|
||||
loop1:
|
||||
add r2, r10, r10, lsr #1
|
||||
mov r1, r0, lsr r2
|
||||
and r1, r1, #7
|
||||
cmp r1, #2
|
||||
blt skip
|
||||
mcr p15, #2, r10, c0, c0, #0
|
||||
isb
|
||||
mrc p15, #1, r1, c0, c0, #0
|
||||
and r2, r1, #7
|
||||
add r2, r2, #4
|
||||
ldr r4, _FLD_MAX_WAY
|
||||
ands r4, r4, r1, lsr #3
|
||||
clz r5, r4
|
||||
ldr r7, _FLD_MAX_IDX
|
||||
ands r7, r7, r1, lsr #13
|
||||
loop2:
|
||||
mov r9, r4
|
||||
loop3:
|
||||
orr r11, r10, r9, lsl r5
|
||||
orr r11, r11, r7, lsl r2
|
||||
mcr p15, #0, r11, c7, c14, #2
|
||||
subs r9, r9, #1
|
||||
bge loop3
|
||||
subs r7, r7, #1
|
||||
bge loop2
|
||||
skip:
|
||||
add r10, r10, #2
|
||||
cmp r3, r10
|
||||
bgt loop1
|
||||
|
||||
finished:
|
||||
dsb
|
||||
isb
|
||||
pop {r4-r11}
|
||||
bx lr
|
||||
|
||||
.globl rt_hw_cpu_dcache_disable
|
||||
rt_hw_cpu_dcache_disable:
|
||||
push {r4-r11, lr}
|
||||
bl rt_cpu_dcache_clean_flush
|
||||
mrc p15, #0, r0, c1, c0, #0
|
||||
bic r0, r0, #0x00000004
|
||||
mcr p15, #0, r0, c1, c0, #0
|
||||
pop {r4-r11, lr}
|
||||
bx lr
|
||||
|
||||
.globl rt_hw_cpu_icache_disable
|
||||
rt_hw_cpu_icache_disable:
|
||||
mrc p15, #0, r0, c1, c0, #0
|
||||
bic r0, r0, #0x00001000
|
||||
mcr p15, #0, r0, c1, c0, #0
|
||||
bx lr
|
||||
|
||||
.globl rt_cpu_mmu_disable
|
||||
rt_cpu_mmu_disable:
|
||||
mcr p15, #0, r0, c8, c7, #0 @ invalidate tlb
|
||||
mrc p15, #0, r0, c1, c0, #0
|
||||
bic r0, r0, #1
|
||||
mcr p15, #0, r0, c1, c0, #0 @ clear mmu bit
|
||||
dsb
|
||||
bx lr
|
||||
|
||||
.globl rt_cpu_mmu_enable
|
||||
rt_cpu_mmu_enable:
|
||||
mrc p15, #0, r0, c1, c0, #0
|
||||
orr r0, r0, #0x001
|
||||
mcr p15, #0, r0, c1, c0, #0 @ set mmu enable bit
|
||||
dsb
|
||||
bx lr
|
||||
|
||||
.globl rt_cpu_tlb_set
|
||||
rt_cpu_tlb_set:
|
||||
mcr p15, #0, r0, c2, c0, #0
|
||||
dmb
|
||||
bx lr
|
||||
@@ -1,20 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2011-09-15 Bernard first version
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
#include <board.h>
|
||||
|
||||
/**
|
||||
* @addtogroup AM33xx
|
||||
*/
|
||||
/*@{*/
|
||||
|
||||
/*@}*/
|
||||
@@ -1,306 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2013-07-20 Bernard first version
|
||||
* 2014-04-03 Grissiom many enhancements
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <board.h>
|
||||
|
||||
#include "gic.h"
|
||||
#include "cp15.h"
|
||||
|
||||
struct arm_gic
|
||||
{
|
||||
rt_uint32_t offset;
|
||||
|
||||
rt_uint32_t dist_hw_base;
|
||||
rt_uint32_t cpu_hw_base;
|
||||
};
|
||||
static struct arm_gic _gic_table[ARM_GIC_MAX_NR];
|
||||
|
||||
#define GIC_CPU_CTRL(hw_base) __REG32((hw_base) + 0x00)
|
||||
#define GIC_CPU_PRIMASK(hw_base) __REG32((hw_base) + 0x04)
|
||||
#define GIC_CPU_BINPOINT(hw_base) __REG32((hw_base) + 0x08)
|
||||
#define GIC_CPU_INTACK(hw_base) __REG32((hw_base) + 0x0c)
|
||||
#define GIC_CPU_EOI(hw_base) __REG32((hw_base) + 0x10)
|
||||
#define GIC_CPU_RUNNINGPRI(hw_base) __REG32((hw_base) + 0x14)
|
||||
#define GIC_CPU_HIGHPRI(hw_base) __REG32((hw_base) + 0x18)
|
||||
|
||||
#define GIC_DIST_CTRL(hw_base) __REG32((hw_base) + 0x000)
|
||||
#define GIC_DIST_TYPE(hw_base) __REG32((hw_base) + 0x004)
|
||||
#define GIC_DIST_IGROUP(hw_base, n) __REG32((hw_base) + 0x080 + ((n)/32) * 4)
|
||||
#define GIC_DIST_ENABLE_SET(hw_base, n) __REG32((hw_base) + 0x100 + ((n)/32) * 4)
|
||||
#define GIC_DIST_ENABLE_CLEAR(hw_base, n) __REG32((hw_base) + 0x180 + ((n)/32) * 4)
|
||||
#define GIC_DIST_PENDING_SET(hw_base, n) __REG32((hw_base) + 0x200 + ((n)/32) * 4)
|
||||
#define GIC_DIST_PENDING_CLEAR(hw_base, n) __REG32((hw_base) + 0x280 + ((n)/32) * 4)
|
||||
#define GIC_DIST_ACTIVE_SET(hw_base, n) __REG32((hw_base) + 0x300 + ((n)/32) * 4)
|
||||
#define GIC_DIST_ACTIVE_CLEAR(hw_base, n) __REG32((hw_base) + 0x380 + ((n)/32) * 4)
|
||||
#define GIC_DIST_PRI(hw_base, n) __REG32((hw_base) + 0x400 + ((n)/4) * 4)
|
||||
#define GIC_DIST_TARGET(hw_base, n) __REG32((hw_base) + 0x800 + ((n)/4) * 4)
|
||||
#define GIC_DIST_CONFIG(hw_base, n) __REG32((hw_base) + 0xc00 + ((n)/16) * 4)
|
||||
#define GIC_DIST_SOFTINT(hw_base) __REG32((hw_base) + 0xf00)
|
||||
#define GIC_DIST_CPENDSGI(hw_base, n) __REG32((hw_base) + 0xf10 + ((n)/4) * 4)
|
||||
#define GIC_DIST_ICPIDR2(hw_base) __REG32((hw_base) + 0xfe8)
|
||||
|
||||
static unsigned int _gic_max_irq;
|
||||
|
||||
int arm_gic_get_active_irq(rt_uint32_t index)
|
||||
{
|
||||
int irq;
|
||||
|
||||
RT_ASSERT(index < ARM_GIC_MAX_NR);
|
||||
|
||||
irq = GIC_CPU_INTACK(_gic_table[index].cpu_hw_base);
|
||||
irq += _gic_table[index].offset;
|
||||
return irq;
|
||||
}
|
||||
|
||||
void arm_gic_ack(rt_uint32_t index, int irq)
|
||||
{
|
||||
rt_uint32_t mask = 1 << (irq % 32);
|
||||
|
||||
RT_ASSERT(index < ARM_GIC_MAX_NR);
|
||||
|
||||
irq = irq - _gic_table[index].offset;
|
||||
RT_ASSERT(irq >= 0);
|
||||
|
||||
GIC_DIST_ENABLE_CLEAR(_gic_table[index].dist_hw_base, irq) = mask;
|
||||
GIC_CPU_EOI(_gic_table[index].cpu_hw_base) = irq;
|
||||
GIC_DIST_ENABLE_SET(_gic_table[index].dist_hw_base, irq) = mask;
|
||||
}
|
||||
|
||||
void arm_gic_mask(rt_uint32_t index, int irq)
|
||||
{
|
||||
rt_uint32_t mask = 1 << (irq % 32);
|
||||
|
||||
RT_ASSERT(index < ARM_GIC_MAX_NR);
|
||||
|
||||
irq = irq - _gic_table[index].offset;
|
||||
RT_ASSERT(irq >= 0);
|
||||
|
||||
GIC_DIST_ENABLE_CLEAR(_gic_table[index].dist_hw_base, irq) = mask;
|
||||
}
|
||||
|
||||
void arm_gic_clear_pending(rt_uint32_t index, int irq)
|
||||
{
|
||||
rt_uint32_t mask = 1 << (irq % 32);
|
||||
|
||||
RT_ASSERT(index < ARM_GIC_MAX_NR);
|
||||
|
||||
irq = irq - _gic_table[index].offset;
|
||||
RT_ASSERT(irq >= 0);
|
||||
|
||||
GIC_DIST_PENDING_CLEAR(_gic_table[index].dist_hw_base, irq) = mask;
|
||||
}
|
||||
|
||||
void arm_gic_clear_active(rt_uint32_t index, int irq)
|
||||
{
|
||||
rt_uint32_t mask = 1 << (irq % 32);
|
||||
|
||||
RT_ASSERT(index < ARM_GIC_MAX_NR);
|
||||
|
||||
irq = irq - _gic_table[index].offset;
|
||||
RT_ASSERT(irq >= 0);
|
||||
|
||||
GIC_DIST_ACTIVE_CLEAR(_gic_table[index].dist_hw_base, irq) = mask;
|
||||
}
|
||||
|
||||
void arm_gic_set_cpu(rt_uint32_t index, int irq, unsigned int cpumask)
|
||||
{
|
||||
rt_uint32_t old_tgt;
|
||||
|
||||
RT_ASSERT(index < ARM_GIC_MAX_NR);
|
||||
|
||||
irq = irq - _gic_table[index].offset;
|
||||
RT_ASSERT(irq >= 0);
|
||||
|
||||
old_tgt = GIC_DIST_TARGET(_gic_table[index].dist_hw_base, irq);
|
||||
|
||||
old_tgt &= ~(0x0FFUL << ((irq % 4)*8));
|
||||
old_tgt |= cpumask << ((irq % 4)*8);
|
||||
|
||||
GIC_DIST_TARGET(_gic_table[index].dist_hw_base, irq) = old_tgt;
|
||||
}
|
||||
|
||||
void arm_gic_umask(rt_uint32_t index, int irq)
|
||||
{
|
||||
rt_uint32_t mask = 1 << (irq % 32);
|
||||
|
||||
RT_ASSERT(index < ARM_GIC_MAX_NR);
|
||||
|
||||
irq = irq - _gic_table[index].offset;
|
||||
RT_ASSERT(irq >= 0);
|
||||
|
||||
GIC_DIST_ENABLE_SET(_gic_table[index].dist_hw_base, irq) = mask;
|
||||
}
|
||||
|
||||
void arm_gic_dump_type(rt_uint32_t index)
|
||||
{
|
||||
unsigned int gic_type;
|
||||
|
||||
gic_type = GIC_DIST_TYPE(_gic_table[index].dist_hw_base);
|
||||
rt_kprintf("GICv%d on %p, max IRQs: %d, %s security extension(%08x)\n",
|
||||
(GIC_DIST_ICPIDR2(_gic_table[index].dist_hw_base) >> 4) & 0xf,
|
||||
_gic_table[index].dist_hw_base,
|
||||
_gic_max_irq,
|
||||
gic_type & (1 << 10) ? "has" : "no",
|
||||
gic_type);
|
||||
}
|
||||
|
||||
void arm_gic_dump(rt_uint32_t index)
|
||||
{
|
||||
unsigned int i, k;
|
||||
|
||||
k = GIC_CPU_HIGHPRI(_gic_table[index].cpu_hw_base);
|
||||
rt_kprintf("--- high pending priority: %d(%08x)\n", k, k);
|
||||
rt_kprintf("--- hw mask ---\n");
|
||||
for (i = 0; i < _gic_max_irq / 32; i++)
|
||||
{
|
||||
rt_kprintf("0x%08x, ",
|
||||
GIC_DIST_ENABLE_SET(_gic_table[index].dist_hw_base,
|
||||
i * 32));
|
||||
}
|
||||
rt_kprintf("\n--- hw pending ---\n");
|
||||
for (i = 0; i < _gic_max_irq / 32; i++)
|
||||
{
|
||||
rt_kprintf("0x%08x, ",
|
||||
GIC_DIST_PENDING_SET(_gic_table[index].dist_hw_base,
|
||||
i * 32));
|
||||
}
|
||||
rt_kprintf("\n--- hw active ---\n");
|
||||
for (i = 0; i < _gic_max_irq / 32; i++)
|
||||
{
|
||||
rt_kprintf("0x%08x, ",
|
||||
GIC_DIST_ACTIVE_SET(_gic_table[index].dist_hw_base,
|
||||
i * 32));
|
||||
}
|
||||
rt_kprintf("\n");
|
||||
}
|
||||
#ifdef RT_USING_FINSH
|
||||
#include <finsh.h>
|
||||
FINSH_FUNCTION_EXPORT_ALIAS(arm_gic_dump, gic, show gic status);
|
||||
#endif
|
||||
|
||||
int arm_gic_dist_init(rt_uint32_t index, rt_uint32_t dist_base, int irq_start)
|
||||
{
|
||||
unsigned int gic_type, i;
|
||||
rt_uint32_t cpumask = 1 << 0;
|
||||
|
||||
RT_ASSERT(index < ARM_GIC_MAX_NR);
|
||||
|
||||
_gic_table[index].dist_hw_base = dist_base;
|
||||
_gic_table[index].offset = irq_start;
|
||||
|
||||
/* Find out how many interrupts are supported. */
|
||||
gic_type = GIC_DIST_TYPE(dist_base);
|
||||
_gic_max_irq = ((gic_type & 0x1f) + 1) * 32;
|
||||
|
||||
/*
|
||||
* The GIC only supports up to 1020 interrupt sources.
|
||||
* Limit this to either the architected maximum, or the
|
||||
* platform maximum.
|
||||
*/
|
||||
if (_gic_max_irq > 1020)
|
||||
_gic_max_irq = 1020;
|
||||
if (_gic_max_irq > ARM_GIC_NR_IRQS)
|
||||
_gic_max_irq = ARM_GIC_NR_IRQS;
|
||||
|
||||
#ifndef RT_PRETENT_AS_CPU0
|
||||
/* If we are run on the second core, the GIC should have already been setup
|
||||
* by BootStrapProcessor. */
|
||||
if ((rt_cpu_get_smp_id() & 0xF) != 0)
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
cpumask |= cpumask << 8;
|
||||
cpumask |= cpumask << 16;
|
||||
|
||||
GIC_DIST_CTRL(dist_base) = 0x0;
|
||||
|
||||
/* Set all global interrupts to be level triggered, active low. */
|
||||
for (i = 32; i < _gic_max_irq; i += 16)
|
||||
GIC_DIST_CONFIG(dist_base, i) = 0x0;
|
||||
|
||||
/* Set all global interrupts to this CPU only. */
|
||||
for (i = 32; i < _gic_max_irq; i += 4)
|
||||
GIC_DIST_TARGET(dist_base, i) = cpumask;
|
||||
|
||||
/* Set priority on all interrupts. */
|
||||
for (i = 0; i < _gic_max_irq; i += 4)
|
||||
GIC_DIST_PRI(dist_base, i) = 0xa0a0a0a0;
|
||||
|
||||
/* Disable all interrupts. */
|
||||
for (i = 0; i < _gic_max_irq; i += 32)
|
||||
GIC_DIST_ENABLE_CLEAR(dist_base, i) = 0xffffffff;
|
||||
/* All interrupts defaults to IGROUP1(IRQ). */
|
||||
for (i = 0; i < _gic_max_irq; i += 32)
|
||||
GIC_DIST_IGROUP(dist_base, i) = 0xffffffff;
|
||||
|
||||
/* Enable group0 and group1 interrupt forwarding. */
|
||||
GIC_DIST_CTRL(dist_base) = 0x03;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int arm_gic_cpu_init(rt_uint32_t index, rt_uint32_t cpu_base)
|
||||
{
|
||||
RT_ASSERT(index < ARM_GIC_MAX_NR);
|
||||
|
||||
_gic_table[index].cpu_hw_base = cpu_base;
|
||||
|
||||
#ifndef RT_PRETENT_AS_CPU0
|
||||
/* If we are run on the second core, the GIC should have already been setup
|
||||
* by BootStrapProcessor. */
|
||||
if ((rt_cpu_get_smp_id() & 0xF) != 0)
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
GIC_CPU_PRIMASK(cpu_base) = 0xf0;
|
||||
/* Enable CPU interrupt */
|
||||
GIC_CPU_CTRL(cpu_base) = 0x01;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void arm_gic_set_group(rt_uint32_t index, int vector, int group)
|
||||
{
|
||||
/* As for GICv2, there are only group0 and group1. */
|
||||
RT_ASSERT(group <= 1);
|
||||
RT_ASSERT(vector < _gic_max_irq);
|
||||
|
||||
if (group == 0)
|
||||
{
|
||||
GIC_DIST_IGROUP(_gic_table[index].dist_hw_base,
|
||||
vector) &= ~(1 << (vector % 32));
|
||||
}
|
||||
else if (group == 1)
|
||||
{
|
||||
GIC_DIST_IGROUP(_gic_table[index].dist_hw_base,
|
||||
vector) |= (1 << (vector % 32));
|
||||
}
|
||||
}
|
||||
|
||||
void arm_gic_trigger(rt_uint32_t index, int target_cpu, int irq)
|
||||
{
|
||||
unsigned int reg;
|
||||
|
||||
RT_ASSERT(irq <= 15);
|
||||
RT_ASSERT(target_cpu <= 255);
|
||||
|
||||
reg = (target_cpu << 16) | irq;
|
||||
GIC_DIST_SOFTINT(_gic_table[index].dist_hw_base) = reg;
|
||||
}
|
||||
|
||||
void arm_gic_clear_sgi(rt_uint32_t index, int target_cpu, int irq)
|
||||
{
|
||||
RT_ASSERT(irq <= 15);
|
||||
RT_ASSERT(target_cpu <= 255);
|
||||
|
||||
GIC_DIST_CPENDSGI(_gic_table[index].dist_hw_base, irq) = target_cpu << (irq % 4);
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2013-07-20 Bernard first version
|
||||
*/
|
||||
|
||||
#ifndef __GIC_H__
|
||||
#define __GIC_H__
|
||||
|
||||
int arm_gic_dist_init(rt_uint32_t index, rt_uint32_t dist_base, int irq_start);
|
||||
int arm_gic_cpu_init(rt_uint32_t index, rt_uint32_t cpu_base);
|
||||
|
||||
void arm_gic_mask(rt_uint32_t index, int irq);
|
||||
void arm_gic_umask(rt_uint32_t index, int irq);
|
||||
void arm_gic_set_cpu(rt_uint32_t index, int irq, unsigned int cpumask);
|
||||
void arm_gic_set_group(rt_uint32_t index, int vector, int group);
|
||||
|
||||
int arm_gic_get_active_irq(rt_uint32_t index);
|
||||
void arm_gic_ack(rt_uint32_t index, int irq);
|
||||
|
||||
void arm_gic_trigger(rt_uint32_t index, int target_cpu, int irq);
|
||||
void arm_gic_clear_sgi(rt_uint32_t index, int target_cpu, int irq);
|
||||
|
||||
void arm_gic_dump_type(rt_uint32_t index);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,126 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2013-07-06 Bernard first version
|
||||
* 2014-04-03 Grissiom port to VMM
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
#include "realview.h"
|
||||
#include "gic.h"
|
||||
|
||||
#define MAX_HANDLERS NR_IRQS_PBA8
|
||||
|
||||
extern volatile rt_atomic_t rt_interrupt_nest;
|
||||
|
||||
/* exception and interrupt handler table */
|
||||
struct rt_irq_desc isr_table[MAX_HANDLERS];
|
||||
|
||||
/* Those varibles will be accessed in ISR, so we need to share them. */
|
||||
rt_uint32_t rt_interrupt_from_thread rt_section(".bss.share.int");
|
||||
rt_uint32_t rt_interrupt_to_thread rt_section(".bss.share.int");
|
||||
rt_uint32_t rt_thread_switch_interrupt_flag rt_section(".bss.share.int");
|
||||
|
||||
const unsigned int VECTOR_BASE = 0x00;
|
||||
extern void rt_cpu_vector_set_base(unsigned int addr);
|
||||
extern int system_vectors;
|
||||
|
||||
static void rt_hw_vector_init(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will initialize hardware interrupt
|
||||
*/
|
||||
void rt_hw_interrupt_init(void)
|
||||
{
|
||||
rt_uint32_t gic_cpu_base;
|
||||
rt_uint32_t gic_dist_base;
|
||||
|
||||
/* initialize vector table */
|
||||
rt_hw_vector_init();
|
||||
|
||||
/* initialize exceptions table */
|
||||
rt_memset(isr_table, 0x00, sizeof(isr_table));
|
||||
|
||||
/* initialize ARM GIC */
|
||||
gic_dist_base = REALVIEW_GIC_DIST_BASE;
|
||||
gic_cpu_base = REALVIEW_GIC_CPU_BASE;
|
||||
|
||||
arm_gic_dist_init(0, gic_dist_base, 0);
|
||||
arm_gic_cpu_init(0, gic_cpu_base);
|
||||
/*arm_gic_dump_type(0);*/
|
||||
|
||||
/* init interrupt nest, and context in thread sp */
|
||||
rt_interrupt_nest = 0;
|
||||
rt_interrupt_from_thread = 0;
|
||||
rt_interrupt_to_thread = 0;
|
||||
rt_thread_switch_interrupt_flag = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will mask a interrupt.
|
||||
* @param vector the interrupt number
|
||||
*/
|
||||
void rt_hw_interrupt_mask(int vector)
|
||||
{
|
||||
arm_gic_mask(0, vector);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will un-mask a interrupt.
|
||||
* @param vector the interrupt number
|
||||
*/
|
||||
void rt_hw_interrupt_umask(int vector)
|
||||
{
|
||||
arm_gic_umask(0, vector);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will install a interrupt service routine to a interrupt.
|
||||
* @param vector the interrupt number
|
||||
* @param new_handler the interrupt service routine to be installed
|
||||
* @param old_handler the old interrupt service routine
|
||||
*/
|
||||
rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
|
||||
void *param, const char *name)
|
||||
{
|
||||
rt_isr_handler_t old_handler = RT_NULL;
|
||||
|
||||
if (vector < MAX_HANDLERS)
|
||||
{
|
||||
old_handler = isr_table[vector].handler;
|
||||
|
||||
if (handler != RT_NULL)
|
||||
{
|
||||
#ifdef RT_USING_INTERRUPT_INFO
|
||||
rt_strncpy(isr_table[vector].name, name, RT_NAME_MAX);
|
||||
#endif /* RT_USING_INTERRUPT_INFO */
|
||||
isr_table[vector].handler = handler;
|
||||
isr_table[vector].param = param;
|
||||
}
|
||||
}
|
||||
|
||||
return old_handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger a software IRQ
|
||||
*
|
||||
* Since we are running in single core, the target CPU are always CPU0.
|
||||
*/
|
||||
void rt_hw_interrupt_trigger(int vector)
|
||||
{
|
||||
arm_gic_trigger(0, 1, vector);
|
||||
}
|
||||
|
||||
void rt_hw_interrupt_clear(int vector)
|
||||
{
|
||||
arm_gic_clear_sgi(0, 1, vector);
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2013-07-06 Bernard first version
|
||||
*/
|
||||
|
||||
#ifndef __INTERRUPT_H__
|
||||
#define __INTERRUPT_H__
|
||||
|
||||
#define INT_IRQ 0x00
|
||||
#define INT_FIQ 0x01
|
||||
|
||||
#define INTC_REVISION(hw_base) REG32((hw_base) + 0x0)
|
||||
#define INTC_SYSCONFIG(hw_base) REG32((hw_base) + 0x10)
|
||||
#define INTC_SYSSTATUS(hw_base) REG32((hw_base) + 0x14)
|
||||
#define INTC_SIR_IRQ(hw_base) REG32((hw_base) + 0x40)
|
||||
#define INTC_SIR_FIQ(hw_base) REG32((hw_base) + 0x44)
|
||||
#define INTC_CONTROL(hw_base) REG32((hw_base) + 0x48)
|
||||
#define INTC_PROTECTION(hw_base) REG32((hw_base) + 0x4c)
|
||||
#define INTC_IDLE(hw_base) REG32((hw_base) + 0x50)
|
||||
#define INTC_IRQ_PRIORITY(hw_base) REG32((hw_base) + 0x60)
|
||||
#define INTC_FIQ_PRIORITY(hw_base) REG32((hw_base) + 0x64)
|
||||
#define INTC_THRESHOLD(hw_base) REG32((hw_base) + 0x68)
|
||||
#define INTC_SICR(hw_base) REG32((hw_base) + 0x6c)
|
||||
#define INTC_SCR(hw_base, n) REG32((hw_base) + 0x70 + ((n) * 0x04))
|
||||
#define INTC_ITR(hw_base, n) REG32((hw_base) + 0x80 + ((n) * 0x20))
|
||||
#define INTC_MIR(hw_base, n) REG32((hw_base) + 0x84 + ((n) * 0x20))
|
||||
#define INTC_MIR_CLEAR(hw_base, n) REG32((hw_base) + 0x88 + ((n) * 0x20))
|
||||
#define INTC_MIR_SET(hw_base, n) REG32((hw_base) + 0x8c + ((n) * 0x20))
|
||||
#define INTC_ISR_SET(hw_base, n) REG32((hw_base) + 0x90 + ((n) * 0x20))
|
||||
#define INTC_ISR_CLEAR(hw_base, n) REG32((hw_base) + 0x94 + ((n) * 0x20))
|
||||
#define INTC_PENDING_IRQ(hw_base, n) REG32((hw_base) + 0x98 + ((n) * 0x20))
|
||||
#define INTC_PENDING_FIQ(hw_base, n) REG32((hw_base) + 0x9c + ((n) * 0x20))
|
||||
#define INTC_ILR(hw_base, n) REG32((hw_base) + 0x100 + ((n) * 0x04))
|
||||
|
||||
void rt_hw_interrupt_control(int vector, int priority, int route);
|
||||
int rt_hw_interrupt_get_active(int fiq_irq);
|
||||
void rt_hw_interrupt_ack(int fiq_irq);
|
||||
void rt_hw_interrupt_trigger(int vector);
|
||||
void rt_hw_interrupt_clear(int vector);
|
||||
|
||||
#endif
|
||||
@@ -1,203 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2012-01-10 bernard porting to AM1808
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <rthw.h>
|
||||
#include <board.h>
|
||||
|
||||
#include "cp15.h"
|
||||
|
||||
#define DESC_SEC (0x2)
|
||||
#define CB (3<<2) //cache_on, write_back
|
||||
#define CNB (2<<2) //cache_on, write_through
|
||||
#define NCB (1<<2) //cache_off,WR_BUF on
|
||||
#define NCNB (0<<2) //cache_off,WR_BUF off
|
||||
#define AP_RW (3<<10) //supervisor=RW, user=RW
|
||||
#define AP_RO (2<<10) //supervisor=RW, user=RO
|
||||
#define XN (1<<4) // eXecute Never
|
||||
|
||||
#define DOMAIN_FAULT (0x0)
|
||||
#define DOMAIN_CHK (0x1)
|
||||
#define DOMAIN_NOTCHK (0x3)
|
||||
#define DOMAIN0 (0x0<<5)
|
||||
#define DOMAIN1 (0x1<<5)
|
||||
|
||||
#define DOMAIN0_ATTR (DOMAIN_CHK<<0)
|
||||
#define DOMAIN1_ATTR (DOMAIN_FAULT<<2)
|
||||
|
||||
/* Read/Write, cache, write back */
|
||||
#define RW_CB (AP_RW|DOMAIN0|CB|DESC_SEC)
|
||||
/* Read/Write, cache, write through */
|
||||
#define RW_CNB (AP_RW|DOMAIN0|CNB|DESC_SEC)
|
||||
/* Read/Write without cache and write buffer */
|
||||
#define RW_NCNB (AP_RW|DOMAIN0|NCNB|DESC_SEC)
|
||||
/* Read/Write without cache and write buffer, no execute */
|
||||
#define RW_NCNBXN (AP_RW|DOMAIN0|NCNB|DESC_SEC|XN)
|
||||
/* Read/Write without cache and write buffer */
|
||||
#define RW_FAULT (AP_RW|DOMAIN1|NCNB|DESC_SEC)
|
||||
|
||||
/* dump 2nd level page table */
|
||||
void rt_hw_cpu_dump_page_table_2nd(rt_uint32_t *ptb)
|
||||
{
|
||||
int i;
|
||||
int fcnt = 0;
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
rt_uint32_t pte2 = ptb[i];
|
||||
if ((pte2 & 0x3) == 0)
|
||||
{
|
||||
if (fcnt == 0)
|
||||
rt_kprintf(" ");
|
||||
rt_kprintf("%04x: ", i);
|
||||
fcnt++;
|
||||
if (fcnt == 16)
|
||||
{
|
||||
rt_kprintf("fault\n");
|
||||
fcnt = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (fcnt != 0)
|
||||
{
|
||||
rt_kprintf("fault\n");
|
||||
fcnt = 0;
|
||||
}
|
||||
|
||||
rt_kprintf(" %04x: %x: ", i, pte2);
|
||||
if ((pte2 & 0x3) == 0x1)
|
||||
{
|
||||
rt_kprintf("L,ap:%x,xn:%d,texcb:%02x\n",
|
||||
((pte2 >> 7) | (pte2 >> 4))& 0xf,
|
||||
(pte2 >> 15) & 0x1,
|
||||
((pte2 >> 10) | (pte2 >> 2)) & 0x1f);
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_kprintf("S,ap:%x,xn:%d,texcb:%02x\n",
|
||||
((pte2 >> 7) | (pte2 >> 4))& 0xf, pte2 & 0x1,
|
||||
((pte2 >> 4) | (pte2 >> 2)) & 0x1f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rt_hw_cpu_dump_page_table(rt_uint32_t *ptb)
|
||||
{
|
||||
int i;
|
||||
int fcnt = 0;
|
||||
|
||||
rt_kprintf("page table@%p\n", ptb);
|
||||
for (i = 0; i < 1024*4; i++)
|
||||
{
|
||||
rt_uint32_t pte1 = ptb[i];
|
||||
if ((pte1 & 0x3) == 0)
|
||||
{
|
||||
rt_kprintf("%03x: ", i);
|
||||
fcnt++;
|
||||
if (fcnt == 16)
|
||||
{
|
||||
rt_kprintf("fault\n");
|
||||
fcnt = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (fcnt != 0)
|
||||
{
|
||||
rt_kprintf("fault\n");
|
||||
fcnt = 0;
|
||||
}
|
||||
|
||||
rt_kprintf("%03x: %08x: ", i, pte1);
|
||||
if ((pte1 & 0x3) == 0x3)
|
||||
{
|
||||
rt_kprintf("LPAE\n");
|
||||
}
|
||||
else if ((pte1 & 0x3) == 0x1)
|
||||
{
|
||||
rt_kprintf("pte,ns:%d,domain:%d\n",
|
||||
(pte1 >> 3) & 0x1, (pte1 >> 5) & 0xf);
|
||||
/*
|
||||
*rt_hw_cpu_dump_page_table_2nd((void*)((pte1 & 0xfffffc000)
|
||||
* - 0x80000000 + 0xC0000000));
|
||||
*/
|
||||
}
|
||||
else if (pte1 & (1 << 18))
|
||||
{
|
||||
rt_kprintf("super section,ns:%d,ap:%x,xn:%d,texcb:%02x\n",
|
||||
(pte1 >> 19) & 0x1,
|
||||
((pte1 >> 13) | (pte1 >> 10))& 0xf,
|
||||
(pte1 >> 4) & 0x1,
|
||||
((pte1 >> 10) | (pte1 >> 2)) & 0x1f);
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_kprintf("section,ns:%d,ap:%x,"
|
||||
"xn:%d,texcb:%02x,domain:%d\n",
|
||||
(pte1 >> 19) & 0x1,
|
||||
((pte1 >> 13) | (pte1 >> 10))& 0xf,
|
||||
(pte1 >> 4) & 0x1,
|
||||
(((pte1 & (0x7 << 12)) >> 10) |
|
||||
((pte1 & 0x0c) >> 2)) & 0x1f,
|
||||
(pte1 >> 5) & 0xf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* level1 page table, each entry for 1MB memory. */
|
||||
volatile static unsigned long MMUTable[4*1024] __attribute__((aligned(16*1024)));
|
||||
void rt_hw_mmu_setmtt(rt_uint32_t vaddrStart,
|
||||
rt_uint32_t vaddrEnd,
|
||||
rt_uint32_t paddrStart,
|
||||
rt_uint32_t attr)
|
||||
{
|
||||
volatile rt_uint32_t *pTT;
|
||||
volatile int i, nSec;
|
||||
pTT = (rt_uint32_t *)MMUTable + (vaddrStart >> 20);
|
||||
nSec = (vaddrEnd >> 20) - (vaddrStart >> 20);
|
||||
for(i = 0; i <= nSec; i++)
|
||||
{
|
||||
*pTT = attr | (((paddrStart >> 20) + i) << 20);
|
||||
pTT++;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long rt_hw_set_domain_register(unsigned long domain_val)
|
||||
{
|
||||
unsigned long old_domain;
|
||||
|
||||
asm volatile ("mrc p15, 0, %0, c3, c0\n" : "=r" (old_domain));
|
||||
asm volatile ("mcr p15, 0, %0, c3, c0\n" : :"r" (domain_val) : "memory");
|
||||
|
||||
return old_domain;
|
||||
}
|
||||
|
||||
void rt_hw_mmu_init(void)
|
||||
{
|
||||
rt_hw_cpu_dcache_disable();
|
||||
rt_hw_cpu_icache_disable();
|
||||
rt_cpu_mmu_disable();
|
||||
|
||||
/* set page table */
|
||||
/* 4G 1:1 memory */
|
||||
rt_hw_mmu_setmtt(0, 0xffffffff-1, 0, RW_CB);
|
||||
/* IO memory region */
|
||||
rt_hw_mmu_setmtt(0x44000000, 0x80000000-1, 0x44000000, RW_NCNBXN);
|
||||
|
||||
/*rt_hw_cpu_dump_page_table(MMUTable);*/
|
||||
rt_hw_set_domain_register(0x55555555);
|
||||
|
||||
rt_cpu_tlb_set(MMUTable);
|
||||
|
||||
rt_cpu_mmu_enable();
|
||||
|
||||
rt_hw_cpu_icache_enable();
|
||||
rt_hw_cpu_dcache_enable();
|
||||
}
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
*/
|
||||
#include <rtthread.h>
|
||||
#include "pmu.h"
|
||||
|
||||
void rt_hw_pmu_dump_feature(void)
|
||||
{
|
||||
unsigned long reg;
|
||||
|
||||
reg = rt_hw_pmu_get_control();
|
||||
rt_kprintf("ARM PMU Implementor: %c, ID code: %02x, %d counters\n",
|
||||
reg >> 24, (reg >> 16) & 0xff, (reg >> 11) & 0x1f);
|
||||
RT_ASSERT(ARM_PMU_CNTER_NR == ((reg >> 11) & 0x1f));
|
||||
}
|
||||
@@ -1,159 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
*/
|
||||
#ifndef __PMU_H__
|
||||
#define __PMU_H__
|
||||
|
||||
#include "board.h"
|
||||
|
||||
/* Number of counters */
|
||||
#define ARM_PMU_CNTER_NR 4
|
||||
|
||||
enum rt_hw_pmu_event_type {
|
||||
ARM_PMU_EVENT_PMNC_SW_INCR = 0x00,
|
||||
ARM_PMU_EVENT_L1_ICACHE_REFILL = 0x01,
|
||||
ARM_PMU_EVENT_ITLB_REFILL = 0x02,
|
||||
ARM_PMU_EVENT_L1_DCACHE_REFILL = 0x03,
|
||||
ARM_PMU_EVENT_L1_DCACHE_ACCESS = 0x04,
|
||||
ARM_PMU_EVENT_DTLB_REFILL = 0x05,
|
||||
ARM_PMU_EVENT_MEM_READ = 0x06,
|
||||
ARM_PMU_EVENT_MEM_WRITE = 0x07,
|
||||
ARM_PMU_EVENT_INSTR_EXECUTED = 0x08,
|
||||
ARM_PMU_EVENT_EXC_TAKEN = 0x09,
|
||||
ARM_PMU_EVENT_EXC_EXECUTED = 0x0A,
|
||||
ARM_PMU_EVENT_CID_WRITE = 0x0B,
|
||||
};
|
||||
|
||||
/* Enable bit */
|
||||
#define ARM_PMU_PMCR_E (0x01 << 0)
|
||||
/* Event counter reset */
|
||||
#define ARM_PMU_PMCR_P (0x01 << 1)
|
||||
/* Cycle counter reset */
|
||||
#define ARM_PMU_PMCR_C (0x01 << 2)
|
||||
/* Cycle counter divider */
|
||||
#define ARM_PMU_PMCR_D (0x01 << 3)
|
||||
|
||||
#ifdef __GNUC__
|
||||
rt_inline void rt_hw_pmu_enable_cnt(int divide64)
|
||||
{
|
||||
unsigned long pmcr;
|
||||
unsigned long pmcntenset;
|
||||
|
||||
asm volatile ("mrc p15, 0, %0, c9, c12, 0" : "=r"(pmcr));
|
||||
pmcr |= ARM_PMU_PMCR_E | ARM_PMU_PMCR_P | ARM_PMU_PMCR_C;
|
||||
if (divide64)
|
||||
pmcr |= ARM_PMU_PMCR_D;
|
||||
else
|
||||
pmcr &= ~ARM_PMU_PMCR_D;
|
||||
asm volatile ("mcr p15, 0, %0, c9, c12, 0" :: "r"(pmcr));
|
||||
|
||||
/* enable all the counters */
|
||||
pmcntenset = ~0;
|
||||
asm volatile ("mcr p15, 0, %0, c9, c12, 1" :: "r"(pmcntenset));
|
||||
/* clear overflows(just in case) */
|
||||
asm volatile ("mcr p15, 0, %0, c9, c12, 3" :: "r"(pmcntenset));
|
||||
}
|
||||
|
||||
rt_inline unsigned long rt_hw_pmu_get_control(void)
|
||||
{
|
||||
unsigned long pmcr;
|
||||
asm ("mrc p15, 0, %0, c9, c12, 0" : "=r"(pmcr));
|
||||
return pmcr;
|
||||
}
|
||||
|
||||
rt_inline unsigned long rt_hw_pmu_get_ceid(void)
|
||||
{
|
||||
unsigned long reg;
|
||||
/* only PMCEID0 is supported, PMCEID1 is RAZ. */
|
||||
asm ("mrc p15, 0, %0, c9, c12, 6" : "=r"(reg));
|
||||
return reg;
|
||||
}
|
||||
|
||||
rt_inline unsigned long rt_hw_pmu_get_cnten(void)
|
||||
{
|
||||
unsigned long pmcnt;
|
||||
asm ("mrc p15, 0, %0, c9, c12, 1" : "=r"(pmcnt));
|
||||
return pmcnt;
|
||||
}
|
||||
|
||||
rt_inline void rt_hw_pmu_reset_cycle(void)
|
||||
{
|
||||
unsigned long pmcr;
|
||||
|
||||
asm volatile ("mrc p15, 0, %0, c9, c12, 0" : "=r"(pmcr));
|
||||
pmcr |= ARM_PMU_PMCR_C;
|
||||
asm volatile ("mcr p15, 0, %0, c9, c12, 0" :: "r"(pmcr));
|
||||
asm volatile ("isb");
|
||||
}
|
||||
|
||||
rt_inline void rt_hw_pmu_reset_event(void)
|
||||
{
|
||||
unsigned long pmcr;
|
||||
|
||||
asm volatile ("mrc p15, 0, %0, c9, c12, 0" : "=r"(pmcr));
|
||||
pmcr |= ARM_PMU_PMCR_P;
|
||||
asm volatile ("mcr p15, 0, %0, c9, c12, 0" :: "r"(pmcr));
|
||||
asm volatile ("isb");
|
||||
}
|
||||
|
||||
rt_inline unsigned long rt_hw_pmu_get_cycle(void)
|
||||
{
|
||||
unsigned long cyc;
|
||||
asm volatile ("isb");
|
||||
asm volatile ("mrc p15, 0, %0, c9, c13, 0" : "=r"(cyc));
|
||||
return cyc;
|
||||
}
|
||||
|
||||
rt_inline void rt_hw_pmu_select_counter(int idx)
|
||||
{
|
||||
RT_ASSERT(idx < ARM_PMU_CNTER_NR);
|
||||
|
||||
asm volatile ("mcr p15, 0, %0, c9, c12, 5" : : "r"(idx));
|
||||
/* Linux add an isb here, don't know why here. */
|
||||
asm volatile ("isb");
|
||||
}
|
||||
|
||||
rt_inline void rt_hw_pmu_select_event(int idx,
|
||||
enum rt_hw_pmu_event_type eve)
|
||||
{
|
||||
RT_ASSERT(idx < ARM_PMU_CNTER_NR);
|
||||
|
||||
rt_hw_pmu_select_counter(idx);
|
||||
asm volatile ("mcr p15, 0, %0, c9, c13, 1" : : "r"(eve));
|
||||
}
|
||||
|
||||
rt_inline unsigned long rt_hw_pmu_read_counter(int idx)
|
||||
{
|
||||
unsigned long reg;
|
||||
|
||||
rt_hw_pmu_select_counter(idx);
|
||||
asm volatile ("isb");
|
||||
asm volatile ("mrc p15, 0, %0, c9, c13, 2" : "=r"(reg));
|
||||
return reg;
|
||||
}
|
||||
|
||||
rt_inline unsigned long rt_hw_pmu_get_ovsr(void)
|
||||
{
|
||||
unsigned long reg;
|
||||
asm volatile ("isb");
|
||||
asm ("mrc p15, 0, %0, c9, c12, 3" : "=r"(reg));
|
||||
return reg;
|
||||
}
|
||||
|
||||
rt_inline void rt_hw_pmu_clear_ovsr(unsigned long reg)
|
||||
{
|
||||
asm ("mcr p15, 0, %0, c9, c12, 3" : : "r"(reg));
|
||||
asm volatile ("isb");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void rt_hw_pmu_dump_feature(void);
|
||||
|
||||
#endif /* end of include guard: __PMU_H__ */
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2011-09-23 Bernard the first version
|
||||
* 2011-10-05 Bernard add thumb mode
|
||||
*/
|
||||
#include <rtthread.h>
|
||||
#include <board.h>
|
||||
|
||||
/**
|
||||
* @addtogroup AM33xx
|
||||
*/
|
||||
/*@{*/
|
||||
|
||||
/**
|
||||
* This function will initialize thread stack
|
||||
*
|
||||
* @param tentry the entry of thread
|
||||
* @param parameter the parameter of entry
|
||||
* @param stack_addr the beginning stack address
|
||||
* @param texit the function will be called when thread exit
|
||||
*
|
||||
* @return stack address
|
||||
*/
|
||||
rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter,
|
||||
rt_uint8_t *stack_addr, void *texit)
|
||||
{
|
||||
rt_uint32_t *stk;
|
||||
|
||||
stack_addr += sizeof(rt_uint32_t);
|
||||
stack_addr = (rt_uint8_t *)RT_ALIGN_DOWN((rt_uint32_t)stack_addr, 8);
|
||||
stk = (rt_uint32_t *)stack_addr;
|
||||
*(--stk) = (rt_uint32_t)tentry; /* entry point */
|
||||
*(--stk) = (rt_uint32_t)texit; /* lr */
|
||||
*(--stk) = 0xdeadbeef; /* r12 */
|
||||
*(--stk) = 0xdeadbeef; /* r11 */
|
||||
*(--stk) = 0xdeadbeef; /* r10 */
|
||||
*(--stk) = 0xdeadbeef; /* r9 */
|
||||
*(--stk) = 0xdeadbeef; /* r8 */
|
||||
*(--stk) = 0xdeadbeef; /* r7 */
|
||||
*(--stk) = 0xdeadbeef; /* r6 */
|
||||
*(--stk) = 0xdeadbeef; /* r5 */
|
||||
*(--stk) = 0xdeadbeef; /* r4 */
|
||||
*(--stk) = 0xdeadbeef; /* r3 */
|
||||
*(--stk) = 0xdeadbeef; /* r2 */
|
||||
*(--stk) = 0xdeadbeef; /* r1 */
|
||||
*(--stk) = (rt_uint32_t)parameter; /* r0 : argument */
|
||||
|
||||
/* cpsr */
|
||||
if ((rt_uint32_t)tentry & 0x01)
|
||||
*(--stk) = SVCMODE | 0x20; /* thumb mode */
|
||||
else
|
||||
*(--stk) = SVCMODE; /* arm mode */
|
||||
|
||||
/* return task's current stack address */
|
||||
return (rt_uint8_t *)stk;
|
||||
}
|
||||
|
||||
/*@}*/
|
||||
@@ -1,237 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2013-07-05 Bernard the first version
|
||||
*/
|
||||
|
||||
#include <rtconfig.h>
|
||||
|
||||
.equ Mode_USR, 0x10
|
||||
.equ Mode_FIQ, 0x11
|
||||
.equ Mode_IRQ, 0x12
|
||||
.equ Mode_SVC, 0x13
|
||||
.equ Mode_ABT, 0x17
|
||||
.equ Mode_UND, 0x1B
|
||||
.equ Mode_SYS, 0x1F
|
||||
|
||||
.equ I_Bit, 0x80 @ when I bit is set, IRQ is disabled
|
||||
.equ F_Bit, 0x40 @ when F bit is set, FIQ is disabled
|
||||
|
||||
.equ UND_Stack_Size, 0x00000000
|
||||
.equ SVC_Stack_Size, 0x00000100
|
||||
.equ ABT_Stack_Size, 0x00000000
|
||||
.equ RT_FIQ_STACK_PGSZ, 0x00000000
|
||||
.equ RT_IRQ_STACK_PGSZ, 0x00000100
|
||||
.equ USR_Stack_Size, 0x00000100
|
||||
|
||||
#define ISR_Stack_Size (UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size + \
|
||||
RT_FIQ_STACK_PGSZ + RT_IRQ_STACK_PGSZ)
|
||||
|
||||
.section .data.share.isr
|
||||
/* stack */
|
||||
.globl stack_start
|
||||
.globl stack_top
|
||||
|
||||
.align 3
|
||||
stack_start:
|
||||
.rept ISR_Stack_Size
|
||||
.byte 0
|
||||
.endr
|
||||
stack_top:
|
||||
|
||||
.text
|
||||
/* reset entry */
|
||||
.globl _reset
|
||||
_reset:
|
||||
/* set the cpu to SVC32 mode and disable interrupt */
|
||||
mrs r0, cpsr
|
||||
bic r0, r0, #0x1f
|
||||
orr r0, r0, #0x13
|
||||
msr cpsr_c, r0
|
||||
|
||||
/* setup stack */
|
||||
bl stack_setup
|
||||
|
||||
/* clear .bss */
|
||||
mov r0,#0 /* get a zero */
|
||||
ldr r1,=__bss_start /* bss start */
|
||||
ldr r2,=__bss_end /* bss end */
|
||||
|
||||
bss_loop:
|
||||
cmp r1,r2 /* check if data to clear */
|
||||
strlo r0,[r1],#4 /* clear 4 bytes */
|
||||
blo bss_loop /* loop until done */
|
||||
|
||||
/* call C++ constructors of global objects */
|
||||
ldr r0, =__ctors_start__
|
||||
ldr r1, =__ctors_end__
|
||||
|
||||
ctor_loop:
|
||||
cmp r0, r1
|
||||
beq ctor_end
|
||||
ldr r2, [r0], #4
|
||||
stmfd sp!, {r0-r1}
|
||||
mov lr, pc
|
||||
bx r2
|
||||
ldmfd sp!, {r0-r1}
|
||||
b ctor_loop
|
||||
ctor_end:
|
||||
|
||||
/* start RT-Thread Kernel */
|
||||
ldr pc, _rtthread_startup
|
||||
_rtthread_startup:
|
||||
.word rtthread_startup
|
||||
|
||||
stack_setup:
|
||||
ldr r0, =stack_top
|
||||
|
||||
@ Set the startup stack for svc
|
||||
mov sp, r0
|
||||
|
||||
@ Enter Undefined Instruction Mode and set its Stack Pointer
|
||||
msr cpsr_c, #Mode_UND|I_Bit|F_Bit
|
||||
mov sp, r0
|
||||
sub r0, r0, #UND_Stack_Size
|
||||
|
||||
@ Enter Abort Mode and set its Stack Pointer
|
||||
msr cpsr_c, #Mode_ABT|I_Bit|F_Bit
|
||||
mov sp, r0
|
||||
sub r0, r0, #ABT_Stack_Size
|
||||
|
||||
@ Enter FIQ Mode and set its Stack Pointer
|
||||
msr cpsr_c, #Mode_FIQ|I_Bit|F_Bit
|
||||
mov sp, r0
|
||||
sub r0, r0, #RT_FIQ_STACK_PGSZ
|
||||
|
||||
@ Enter IRQ Mode and set its Stack Pointer
|
||||
msr cpsr_c, #Mode_IRQ|I_Bit|F_Bit
|
||||
mov sp, r0
|
||||
sub r0, r0, #RT_IRQ_STACK_PGSZ
|
||||
|
||||
/* come back to SVC mode */
|
||||
msr cpsr_c, #Mode_SVC|I_Bit|F_Bit
|
||||
bx lr
|
||||
|
||||
/* exception handlers: undef, swi, padt, dabt, resv, irq, fiq */
|
||||
.section .text.isr, "ax"
|
||||
.align 5
|
||||
.globl vector_fiq
|
||||
vector_fiq:
|
||||
stmfd sp!,{r0-r7,lr}
|
||||
bl rt_hw_trap_fiq
|
||||
ldmfd sp!,{r0-r7,lr}
|
||||
subs pc, lr, #4
|
||||
|
||||
.globl rt_interrupt_enter
|
||||
.globl rt_interrupt_leave
|
||||
.globl rt_thread_switch_interrupt_flag
|
||||
.globl rt_interrupt_from_thread
|
||||
.globl rt_interrupt_to_thread
|
||||
|
||||
.globl rt_current_thread
|
||||
.globl vmm_thread
|
||||
.globl vmm_virq_check
|
||||
|
||||
.align 5
|
||||
.globl vector_irq
|
||||
vector_irq:
|
||||
stmfd sp!, {r0-r12,lr}
|
||||
|
||||
bl rt_interrupt_enter
|
||||
bl rt_hw_trap_irq
|
||||
bl rt_interrupt_leave
|
||||
|
||||
@ if rt_thread_switch_interrupt_flag set, jump to
|
||||
@ rt_hw_context_switch_interrupt_do and don't return
|
||||
ldr r0, =rt_thread_switch_interrupt_flag
|
||||
ldr r1, [r0]
|
||||
cmp r1, #1
|
||||
beq rt_hw_context_switch_interrupt_do
|
||||
|
||||
ldmfd sp!, {r0-r12,lr}
|
||||
subs pc, lr, #4
|
||||
|
||||
rt_hw_context_switch_interrupt_do:
|
||||
mov r1, #0 @ clear flag
|
||||
str r1, [r0]
|
||||
|
||||
mov r1, sp @ r1 point to {r0-r3} in stack
|
||||
add sp, sp, #4*4
|
||||
ldmfd sp!, {r4-r12,lr}@ reload saved registers
|
||||
mrs r0, spsr @ get cpsr of interrupt thread
|
||||
sub r2, lr, #4 @ save old task's pc to r2
|
||||
|
||||
@ Switch to SVC mode with no interrupt. If the usr mode guest is
|
||||
@ interrupted, this will just switch to the stack of kernel space.
|
||||
@ save the registers in kernel space won't trigger data abort.
|
||||
msr cpsr_c, #I_Bit|F_Bit|Mode_SVC
|
||||
|
||||
stmfd sp!, {r2} @ push old task's pc
|
||||
stmfd sp!, {r4-r12,lr}@ push old task's lr,r12-r4
|
||||
ldmfd r1, {r1-r4} @ restore r0-r3 of the interrupt thread
|
||||
stmfd sp!, {r1-r4} @ push old task's r0-r3
|
||||
stmfd sp!, {r0} @ push old task's cpsr
|
||||
|
||||
ldr r4, =rt_interrupt_from_thread
|
||||
ldr r5, [r4]
|
||||
str sp, [r5] @ store sp in preempted tasks's TCB
|
||||
|
||||
ldr r6, =rt_interrupt_to_thread
|
||||
ldr r6, [r6]
|
||||
ldr sp, [r6] @ get new task's stack pointer
|
||||
|
||||
ldmfd sp!, {r4} @ pop new task's cpsr to spsr
|
||||
msr spsr_cxsf, r4
|
||||
|
||||
ldmfd sp!, {r0-r12,lr,pc}^ @ pop new task's r0-r12,lr & pc, copy spsr to cpsr
|
||||
|
||||
.macro push_svc_reg
|
||||
sub sp, sp, #17 * 4 @/* Sizeof(struct rt_hw_exp_stack) */
|
||||
stmia sp, {r0 - r12} @/* Calling r0-r12 */
|
||||
mov r0, sp
|
||||
mrs r6, spsr @/* Save CPSR */
|
||||
str lr, [r0, #15*4] @/* Push PC */
|
||||
str r6, [r0, #16*4] @/* Push CPSR */
|
||||
cps #Mode_SVC
|
||||
str sp, [r0, #13*4] @/* Save calling SP */
|
||||
str lr, [r0, #14*4] @/* Save calling PC */
|
||||
.endm
|
||||
|
||||
.align 5
|
||||
.globl vector_swi
|
||||
vector_swi:
|
||||
push_svc_reg
|
||||
bl rt_hw_trap_swi
|
||||
b .
|
||||
|
||||
.align 5
|
||||
.globl vector_undef
|
||||
vector_undef:
|
||||
push_svc_reg
|
||||
bl rt_hw_trap_undef
|
||||
b .
|
||||
|
||||
.align 5
|
||||
.globl vector_pabt
|
||||
vector_pabt:
|
||||
push_svc_reg
|
||||
bl rt_hw_trap_pabt
|
||||
b .
|
||||
|
||||
.align 5
|
||||
.globl vector_dabt
|
||||
vector_dabt:
|
||||
push_svc_reg
|
||||
bl rt_hw_trap_dabt
|
||||
b .
|
||||
|
||||
.align 5
|
||||
.globl vector_resv
|
||||
vector_resv:
|
||||
push_svc_reg
|
||||
bl rt_hw_trap_resv
|
||||
b .
|
||||
@@ -1,187 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2013-07-20 Bernard first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <rthw.h>
|
||||
#include <board.h>
|
||||
|
||||
#include "armv7.h"
|
||||
|
||||
#include "gic.h"
|
||||
|
||||
extern struct rt_thread *rt_current_thread;
|
||||
#if defined(RT_USING_FINSH) && defined(MSH_USING_BUILT_IN_COMMANDS)
|
||||
extern long list_thread(void);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* this function will show registers of CPU
|
||||
*
|
||||
* @param regs the registers point
|
||||
*/
|
||||
void rt_hw_show_register(struct rt_hw_exp_stack *regs)
|
||||
{
|
||||
rt_kprintf("Execption:\n");
|
||||
rt_kprintf("r00:0x%08x r01:0x%08x r02:0x%08x r03:0x%08x\n", regs->r0, regs->r1, regs->r2, regs->r3);
|
||||
rt_kprintf("r04:0x%08x r05:0x%08x r06:0x%08x r07:0x%08x\n", regs->r4, regs->r5, regs->r6, regs->r7);
|
||||
rt_kprintf("r08:0x%08x r09:0x%08x r10:0x%08x\n", regs->r8, regs->r9, regs->r10);
|
||||
rt_kprintf("fp :0x%08x ip :0x%08x\n", regs->fp, regs->ip);
|
||||
rt_kprintf("sp :0x%08x lr :0x%08x pc :0x%08x\n", regs->sp, regs->lr, regs->pc);
|
||||
rt_kprintf("cpsr:0x%08x\n", regs->cpsr);
|
||||
}
|
||||
|
||||
/**
|
||||
* When comes across an instruction which it cannot handle,
|
||||
* it takes the undefined instruction trap.
|
||||
*
|
||||
* @param regs system registers
|
||||
*
|
||||
* @note never invoke this function in application
|
||||
*/
|
||||
void rt_hw_trap_undef(struct rt_hw_exp_stack *regs)
|
||||
{
|
||||
rt_kprintf("undefined instruction:\n");
|
||||
rt_hw_show_register(regs);
|
||||
#if defined(RT_USING_FINSH) && defined(MSH_USING_BUILT_IN_COMMANDS)
|
||||
list_thread();
|
||||
#endif
|
||||
rt_hw_cpu_shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* The software interrupt instruction (SWI) is used for entering
|
||||
* Supervisor mode, usually to request a particular supervisor
|
||||
* function.
|
||||
*
|
||||
* @param regs system registers
|
||||
*
|
||||
* @note never invoke this function in application
|
||||
*/
|
||||
void rt_hw_trap_swi(struct rt_hw_exp_stack *regs)
|
||||
{
|
||||
rt_kprintf("software interrupt:\n");
|
||||
rt_hw_show_register(regs);
|
||||
#if defined(RT_USING_FINSH) && defined(MSH_USING_BUILT_IN_COMMANDS)
|
||||
list_thread();
|
||||
#endif
|
||||
rt_hw_cpu_shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* An abort indicates that the current memory access cannot be completed,
|
||||
* which occurs during an instruction prefetch.
|
||||
*
|
||||
* @param regs system registers
|
||||
*
|
||||
* @note never invoke this function in application
|
||||
*/
|
||||
void rt_hw_trap_pabt(struct rt_hw_exp_stack *regs)
|
||||
{
|
||||
rt_kprintf("prefetch abort:\n");
|
||||
rt_hw_show_register(regs);
|
||||
#if defined(RT_USING_FINSH) && defined(MSH_USING_BUILT_IN_COMMANDS)
|
||||
list_thread();
|
||||
#endif
|
||||
rt_hw_cpu_shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* An abort indicates that the current memory access cannot be completed,
|
||||
* which occurs during a data access.
|
||||
*
|
||||
* @param regs system registers
|
||||
*
|
||||
* @note never invoke this function in application
|
||||
*/
|
||||
void rt_hw_trap_dabt(struct rt_hw_exp_stack *regs)
|
||||
{
|
||||
rt_kprintf("data abort:");
|
||||
rt_hw_show_register(regs);
|
||||
#if defined(RT_USING_FINSH) && defined(MSH_USING_BUILT_IN_COMMANDS)
|
||||
list_thread();
|
||||
#endif
|
||||
rt_hw_cpu_shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Normally, system will never reach here
|
||||
*
|
||||
* @param regs system registers
|
||||
*
|
||||
* @note never invoke this function in application
|
||||
*/
|
||||
void rt_hw_trap_resv(struct rt_hw_exp_stack *regs)
|
||||
{
|
||||
rt_kprintf("reserved trap:\n");
|
||||
rt_hw_show_register(regs);
|
||||
#if defined(RT_USING_FINSH) && defined(MSH_USING_BUILT_IN_COMMANDS)
|
||||
list_thread();
|
||||
#endif
|
||||
rt_hw_cpu_shutdown();
|
||||
}
|
||||
|
||||
#define GIC_ACK_INTID_MASK 0x000003ff
|
||||
|
||||
void rt_hw_trap_irq(void)
|
||||
{
|
||||
void *param;
|
||||
unsigned long ir;
|
||||
unsigned long fullir;
|
||||
rt_isr_handler_t isr_func;
|
||||
extern struct rt_irq_desc isr_table[];
|
||||
|
||||
fullir = arm_gic_get_active_irq(0);
|
||||
ir = fullir & GIC_ACK_INTID_MASK;
|
||||
|
||||
if (ir == 1023)
|
||||
{
|
||||
/* Spurious interrupt */
|
||||
return;
|
||||
}
|
||||
|
||||
/* get interrupt service routine */
|
||||
isr_func = isr_table[ir].handler;
|
||||
#ifdef RT_USING_INTERRUPT_INFO
|
||||
isr_table[ir].counter++;
|
||||
#endif
|
||||
if (isr_func)
|
||||
{
|
||||
/* Interrupt for myself. */
|
||||
param = isr_table[ir].param;
|
||||
/* turn to interrupt service routine */
|
||||
isr_func(ir, param);
|
||||
}
|
||||
|
||||
/* end of interrupt */
|
||||
arm_gic_ack(0, fullir);
|
||||
}
|
||||
|
||||
void rt_hw_trap_fiq(void)
|
||||
{
|
||||
void *param;
|
||||
unsigned long ir;
|
||||
unsigned long fullir;
|
||||
rt_isr_handler_t isr_func;
|
||||
extern struct rt_irq_desc isr_table[];
|
||||
|
||||
fullir = arm_gic_get_active_irq(0);
|
||||
ir = fullir & GIC_ACK_INTID_MASK;
|
||||
|
||||
/* get interrupt service routine */
|
||||
isr_func = isr_table[ir].handler;
|
||||
param = isr_table[ir].param;
|
||||
|
||||
/* turn to interrupt service routine */
|
||||
isr_func(ir, param);
|
||||
|
||||
/* end of interrupt */
|
||||
arm_gic_ack(0, fullir);
|
||||
}
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2013-07-05 Bernard the first version
|
||||
*/
|
||||
#include <rtconfig.h>
|
||||
|
||||
.section .vectors, "ax"
|
||||
.code 32
|
||||
|
||||
.globl system_vectors
|
||||
system_vectors:
|
||||
ldr pc, _vector_reset
|
||||
ldr pc, _vector_undef
|
||||
ldr pc, _vector_swi
|
||||
ldr pc, _vector_pabt
|
||||
ldr pc, _vector_dabt
|
||||
ldr pc, _vector_resv
|
||||
ldr pc, _vector_irq
|
||||
ldr pc, _vector_fiq
|
||||
|
||||
.globl _reset
|
||||
.globl vector_undef
|
||||
.globl vector_swi
|
||||
.globl vector_pabt
|
||||
.globl vector_dabt
|
||||
.globl vector_resv
|
||||
.globl vector_irq
|
||||
.globl vector_fiq
|
||||
|
||||
_vector_reset:
|
||||
.word _reset
|
||||
_vector_undef:
|
||||
.word vector_undef
|
||||
_vector_swi:
|
||||
.word vector_swi
|
||||
_vector_pabt:
|
||||
.word vector_pabt
|
||||
_vector_dabt:
|
||||
.word vector_dabt
|
||||
_vector_resv:
|
||||
.word vector_resv
|
||||
_vector_irq:
|
||||
.word vector_irq
|
||||
_vector_fiq:
|
||||
.word vector_fiq
|
||||
|
||||
.balignl 16,0xdeadbeef
|
||||
Reference in New Issue
Block a user