add mutex example

This commit is contained in:
tensfile 2024-07-03 00:29:12 +08:00
parent 86a62a3d45
commit 4a6a44681f
6 changed files with 496 additions and 0 deletions

View File

@ -0,0 +1,39 @@
cmake_minimum_required(VERSION 3.8)
project(mutex)
set(CMAKE_BUILD_TYPE "Debug")
set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g2 -ggdb")
set(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall")
set(TINY_ROOT ../../../)
include_directories(${TINY_ROOT}/osal/cmsis_os)
include_directories(${TINY_ROOT}/core/include)
include_directories(${TINY_ROOT}/hal/include)
include_directories(${TINY_ROOT}/pm/include)
set(CMSIS_SRCS ${TINY_ROOT}/osal/cmsis_os/cmsis_os.c)
aux_source_directory(${TINY_ROOT}/core CORE_SRCS)
aux_source_directory(${TINY_ROOT}/pm PM_SRCS)
set(ARCH_ROOT ${TINY_ROOT}/arch/linux)
include_directories(${ARCH_ROOT}/common/include)
include_directories(${ARCH_ROOT}/posix/gcc)
aux_source_directory(${ARCH_ROOT}/common ARCH_COMMON_SRCS)
aux_source_directory(${ARCH_ROOT}/posix/gcc ARCH_POSIX_SRCS)
set(ARCH_SRCS ${ARCH_COMMON_SRCS} ${ARCH_POSIX_SRCS})
set(TINY_SRCS ${ARCH_SRCS} ${CMSIS_SRCS} ${EVTDRV_SRCS} ${PM_SRCS} ${CORE_SRCS} )
include_directories(./)
include_directories(./inc)
set(APP_SRCS src/main.c)
add_executable(mutex ${APP_SRCS} ${TINY_SRCS})
target_link_libraries(mutex pthread)

View File

@ -0,0 +1,50 @@
###################################################################
#automatic detection QTOP and LOCALDIR
CUR_DIR := $(patsubst %/,%,$(dir $(realpath $(firstword $(MAKEFILE_LIST)))))
TRYQTOP := $(shell if [ -n "$$QTOP" ] ; then\
echo $$QTOP;\
else\
cd $(CUR_DIR); while /usr/bin/test ! -e qmk ; do \
dir=`cd ../;pwd`; \
if [ "$$dir" = "/" ] ; then \
echo Cannot find QTOP in $(firstword $(MAKEFILE_LIST)) 1>&2; \
exit 1; \
fi ; \
cd $$dir; \
done ; \
pwd; \
fi)
QTOP ?= $(realpath ${TRYQTOP})
ifeq ($(QTOP),)
$(error Please run this in a tree)
endif
LOCALDIR = $(patsubst %/,%,$(subst $(realpath $(QTOP))/,,$(CUR_DIR)))
export QTOP
####################################################################
export BP=Linux_Posix
TREE_LIB_ENABLE=1
lib=
subdirs =
all::
make -C ${QTOP}/arch BP=${BP}
make -C ${QTOP}/kernel BP=${BP}
make -C ${QTOP}/osal BP=${BP}
make -C ${QTOP}/net BP=${BP}
make -C ${QTOP}/devices BP=${BP}
exec =
LD_A_FILES += $(LIBDIR)/libarch.a
LD_A_FILES += $(LIBDIR)/libkernel.a
LD_A_FILES += $(LIBDIR)/libhello_world.a
LD_A_FILES += $(LIBDIR)/libcmsis_os.a
LDFLAGS += -lpthread
include ${QTOP}/qmk/generic/Make.exec

View File

@ -0,0 +1,51 @@
# Mutex Example
This example shows how to use the mutex in TobudOS. The example creates two tasks, each of which increments the shared variable counter. To avoid race conditions, the example uses mutex api to protect the shared resource. The output of the example is
```bash
Task task1: Counter is 1
Task task2: Counter is 2
Task task2: Counter is 3
Task task1: Counter is 4
Task task1: Counter is 5
```
## step1
make sure your develop environment.
- `cmake` and version greater than 3.8.2
- `gcc` `gdb` `make` is installed
## step2
make `build` directory and compile in `build`
```bash
mkdir build && cd build
cmake ..
make
```
## step3
run program !!
```bash
# in build directory
./mutex
```
## other
you can copy this demo to other path, but if you want do it,
you need modify `CMakeLists.txt`. find line
```cmake
set(TINY_ROOT ../../../)
```
and modify `path-to-tinyos`
```cmake
set(TINY_ROOT path-to-tinyos)
```

View File

@ -0,0 +1,236 @@
/**
******************************************************************************
* @file lwipopts.h
* @author MCD Application Team
* @version V1.1.0
* @date 31-July-2013
* @brief lwIP Options Configuration.
* This file is based on Utilities\lwip_v1.4.1\src\include\lwip\opt.h
* and contains the lwIP configuration for the STM32F4x7 demonstration.
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2013 STMicroelectronics</center></h2>
*
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/software_license_agreement_liberty_v2
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
#ifndef __LWIPOPTS_H__
#define __LWIPOPTS_H__
/**
* SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain
* critical regions during buffer allocation, deallocation and memory
* allocation and deallocation.
*/
#define SYS_LIGHTWEIGHT_PROT 1
/**
* NO_SYS==1: Provides VERY minimal functionality. Otherwise,
* use lwIP facilities.
*/
#define NO_SYS 0
/**
* NO_SYS_NO_TIMERS==1: Drop support for sys_timeout when NO_SYS==1
* Mainly for compatibility to old versions.
*/
#define NO_SYS_NO_TIMERS 0
/* ---------- Memory options ---------- */
/* MEM_ALIGNMENT: should be set to the alignment of the CPU for which
lwIP is compiled. 4 byte alignment -> define MEM_ALIGNMENT to 4, 2
byte alignment -> define MEM_ALIGNMENT to 2. */
#define MEM_ALIGNMENT 4
/* MEM_SIZE: the size of the heap memory. If the application will send
a lot of data that needs to be copied, this should be set high. */
#define MEM_SIZE (5 * 1024)
/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application
sends a lot of data out of ROM (or other static memory), this
should be set high. */
#define MEMP_NUM_PBUF 25
/* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One
per active UDP "connection". */
#define MEMP_NUM_UDP_PCB 4
/* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP
connections. */
#define MEMP_NUM_TCP_PCB 6
/* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP
connections. */
#define MEMP_NUM_TCP_PCB_LISTEN 6
/* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP
segments. */
#define MEMP_NUM_TCP_SEG 150
/* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active
timeouts. */
#define MEMP_NUM_SYS_TIMEOUT 6
/* ---------- Pbuf options ---------- */
/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */
#define PBUF_POOL_SIZE 25
/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */
#define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(TCP_MSS + 40 + PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN)
/* ---------- TCP options ---------- */
#define LWIP_TCP 1
#define TCP_TTL 255
/* Controls if TCP should queue segments that arrive out of
order. Define to 0 if your device is low on memory. */
#define TCP_QUEUE_OOSEQ 0
/* TCP Maximum segment size. */
#define TCP_MSS (1500 - 40) /* TCP_MSS = (Ethernet MTU - IP header size - TCP header size) */
/* TCP sender buffer space (bytes). */
#define TCP_SND_BUF (7 * TCP_MSS)
/* TCP_SND_QUEUELEN: TCP sender buffer space (pbufs). This must be at least
as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. */
#define TCP_SND_QUEUELEN (8 * TCP_SND_BUF / TCP_MSS)
/* TCP receive window. */
#define TCP_WND (9 * TCP_MSS)
/* ---------- ICMP options ---------- */
#define LWIP_ICMP 1
/* ---------- DHCP options ---------- */
/* Define LWIP_DHCP to 1 if you want DHCP configuration of
interfaces. DHCP is not implemented in lwIP 0.5.1, however, so
turning this on does currently not work. */
#define LWIP_DHCP 1
/* ---------- UDP options ---------- */
#define LWIP_UDP 1
#define UDP_TTL 255
/* ---------- Statistics options ---------- */
#define LWIP_STATS 0
#define LWIP_PROVIDE_ERRNO 1
/* ---------- link callback options ---------- */
/* LWIP_NETIF_LINK_CALLBACK==1: Support a callback function from an interface
* whenever the link changes (i.e., link down)
*/
#define LWIP_NETIF_LINK_CALLBACK 0
/*
--------------------------------------
---------- Checksum options ----------
--------------------------------------
*/
/*
The STM32F4x7 allows computing and verifying the IP, UDP, TCP and ICMP checksums by hardware:
- To use this feature let the following define uncommented.
- To disable it and process by CPU comment the the checksum.
*/
#define CHECKSUM_BY_HARDWARE
//#undef CHECKSUM_BY_HARDWARE
#ifdef CHECKSUM_BY_HARDWARE
/* CHECKSUM_GEN_IP==0: Generate checksums by hardware for outgoing IP packets.*/
#define CHECKSUM_GEN_IP 0
/* CHECKSUM_GEN_UDP==0: Generate checksums by hardware for outgoing UDP packets.*/
#define CHECKSUM_GEN_UDP 0
/* CHECKSUM_GEN_TCP==0: Generate checksums by hardware for outgoing TCP packets.*/
#define CHECKSUM_GEN_TCP 0
/* CHECKSUM_CHECK_IP==0: Check checksums by hardware for incoming IP packets.*/
#define CHECKSUM_CHECK_IP 0
/* CHECKSUM_CHECK_UDP==0: Check checksums by hardware for incoming UDP packets.*/
#define CHECKSUM_CHECK_UDP 0
/* CHECKSUM_CHECK_TCP==0: Check checksums by hardware for incoming TCP packets.*/
#define CHECKSUM_CHECK_TCP 0
/* CHECKSUM_CHECK_ICMP==0: Check checksums by hardware for incoming ICMP packets.*/
#define CHECKSUM_GEN_ICMP 0
#else
/* CHECKSUM_GEN_IP==1: Generate checksums in software for outgoing IP packets.*/
#define CHECKSUM_GEN_IP 1
/* CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP packets.*/
#define CHECKSUM_GEN_UDP 1
/* CHECKSUM_GEN_TCP==1: Generate checksums in software for outgoing TCP packets.*/
#define CHECKSUM_GEN_TCP 1
/* CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets.*/
#define CHECKSUM_CHECK_IP 1
/* CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets.*/
#define CHECKSUM_CHECK_UDP 1
/* CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets.*/
#define CHECKSUM_CHECK_TCP 1
/* CHECKSUM_CHECK_ICMP==1: Check checksums by hardware for incoming ICMP packets.*/
#define CHECKSUM_GEN_ICMP 1
#endif
#define LWIP_TCPIP_CORE_LOCKING 1
/*
----------------------------------------------
---------- Sequential layer options ----------
----------------------------------------------
*/
/**
* LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c)
*/
#define LWIP_NETCONN 1
/*
------------------------------------
---------- Socket options ----------
------------------------------------
*/
/**
* LWIP_SOCKET==1: Enable Socket API (require to use sockets.c)
*/
#define LWIP_SOCKET 1
/*
---------------------------------
---------- OS options ----------
---------------------------------
*/
#define DEFAULT_UDP_RECVMBOX_SIZE 10
#define DEFAULT_TCP_RECVMBOX_SIZE 10
#define DEFAULT_ACCEPTMBOX_SIZE 10
#define DEFAULT_THREAD_STACKSIZE 1024 * 2
#define TCPIP_THREAD_NAME "lwip"
#define TCPIP_THREAD_STACKSIZE 1024
#define TCPIP_MBOX_SIZE 10
#define TCPIP_THREAD_PRIO 1
#define LWIP_DNS_API_DECLARE_STRUCTS 1
#define LWIP_DNS 1
/** DNS server IP address */
#ifndef DNS_SERVER_ADDRESS
#define DNS_SERVER_ADDRESS(ipaddr) (ip4_addr_set_u32(ipaddr, ipaddr_addr("208.67.222.222"))) /* resolver1.opendns.com */
#endif
/*
----------------------------------------
---------- Lwip Debug options ----------
----------------------------------------
*/
#define LWIP_DEBUG 0
#define ethernet_with_mac 1
#endif /* __LWIPOPTS_H__ */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@ -0,0 +1,51 @@
#ifndef _TOS_CONFIG_H_
#define _TOS_CONFIG_H_
#include "stddef.h"
#include "stdint.h"
#define TOS_CFG_TASK_PRIO_MAX 10u // 配置 TobudOS 默认支持的最大优先级数量
#define TOS_CFG_ROUND_ROBIN_EN 1u // 配置 TobudOS 的内核是否开启时间片轮转
#define TOS_CFG_OBJECT_VERIFY_EN 1u // 配置 TobudOS 是否校验指针合法
#define TOS_CFG_EVENT_EN 1u // TobudOS 事件模块功能宏
#define TOS_CFG_MMHEAP_EN 1u // 配置 TobudOS 是否开启动态内存模块
#define TOS_CFG_MMHEAP_POOL_SIZE 0x100 // 配置 TobudOS 动态内存池大小
#define TOS_CFG_MMHEAP_DEFAULT_POOL_SIZE 0x100 // 配置 TobudOS 动态内存池大小
#define TOS_CFG_MUTEX_EN 1u // 配置 TobudOS 是否开启互斥锁模块
#define TOS_CFG_MESSAGE_QUEUE_EN 1u
#define TOS_CFG_MAIL_QUEUE_EN 1u
#define TOS_CFG_PRIORITY_MESSAGE_QUEUE_EN 1u
#define TOS_CFG_PRIORITY_MAIL_QUEUE_EN 1u
#define TOS_CFG_TIMER_EN 1u // 配置 TobudOS 是否开启软件定时器模块
#define TOS_CFG_SEM_EN 1u // 配置 TobudOS 是否开启信号量模块
#define TOS_CFG_MMBLK_EN 1u
#if (TOS_CFG_QUEUE_EN > 0u)
#define TOS_CFG_MSG_EN 1u
#else
#define TOS_CFG_MSG_EN 0u
#endif
#define TOS_CFG_MSG_POOL_SIZE 10u // 配置 TobudOS 消息队列大小
#define TOS_CFG_IDLE_TASK_STK_SIZE 256u // 配置 TobudOS 空闲任务栈大小
#define TOS_CFG_CPU_TICK_PER_SECOND 1000u // 配置 TobudOS 的 tick 频率
#define TOS_CFG_CPU_CLOCK 1000000u // 配置 TobudOS CPU 频率
#define TOS_CFG_TIMER_AS_PROC 1u // 配置是否将 TIMER 配置成函数模式
#endif

View File

@ -0,0 +1,69 @@
#include "tos_k.h"
#define STK_SIZE_TASK_1 512
#define STK_SIZE_TASK_2 512
#define MAX_COUNT 5
k_stack_t stack_task_1[STK_SIZE_TASK_1];
k_stack_t stack_task_2[STK_SIZE_TASK_2];
k_task_t task_1;
k_task_t task_2;
extern void entry_task_1(void *arg);
extern void entry_task_2(void *arg);
k_mutex_t counter_lock;
static uint32_t counter = 0;
void entry_task_1(void *arg)
{
k_err_t err;
while (K_TRUE) {
if (counter >= MAX_COUNT) {
tos_task_destroy(K_NULL);
}
err = tos_mutex_pend(&counter_lock);
if (err == K_ERR_NONE) {
counter++;
printf("Task %s: Counter is %d\n", tos_task_curr_task_get() -> name, counter);
tos_mutex_post(&counter_lock);
}
if (counter > 50) {
tos_task_destroy(K_NULL);
}
tos_task_delay(300);
}
}
void entry_task_2(void *arg)
{
k_err_t err;
while (K_TRUE) {
if (counter >= MAX_COUNT) {
tos_task_destroy(K_NULL);
}
err = tos_mutex_pend(&counter_lock);
if (err == K_ERR_NONE) {
counter++;
printf("Task %s: Counter is %d\n", tos_task_curr_task_get() -> name, counter);
tos_mutex_post(&counter_lock);
}
tos_task_delay(300);
}
}
int main(void)
{
tos_knl_init();
// 创建临界区保护互斥锁
tos_mutex_create(&counter_lock);
(void)tos_task_create(&task_1, "task1", entry_task_1, NULL,
4, stack_task_1, STK_SIZE_TASK_1, 0);
(void)tos_task_create(&task_2, "task2", entry_task_2, NULL,
4, stack_task_2, STK_SIZE_TASK_2, 0);
tos_knl_start();
}