!15 分离了驱动和协议栈,但性能还需要优化,速度800KB

Merge pull request !15 from ATShining/network-drv
This commit is contained in:
ATShining
2024-01-21 14:09:44 +00:00
committed by Gitee
29 changed files with 1350 additions and 37 deletions

14
.vscode/settings.json vendored
View File

@@ -293,7 +293,19 @@
"semaphore.h": "c",
"libc.h": "c",
"printf.h": "c",
"printf_config.h": "c"
"printf_config.h": "c",
"net_drv_svr.h": "c",
"net_drv_types.h": "c",
"__tree": "c",
"filesystem": "c",
"u_share_mem.h": "c",
"fs_rpc.h": "c",
"net_drv_cli.h": "c",
"deque": "c",
"map": "c",
"regex": "c",
"set": "c",
"stack": "c"
},
"cortex-debug.showRTOS": false,
"cortex-debug.variableUseNaturalFormat": false,

View File

@@ -110,4 +110,4 @@ CONFIG_RT_USING_PIN=y
CONFIG_CPU_TYPE="stm32f1"
CONFIG_RTT_DIR="./"
CONFIG_ARCH="cortex-m3"
CONFIG_KNL_EXRAM=n
CONFIG_KNL_EXRAM=y

View File

@@ -12,8 +12,10 @@ void sram_init(void)
}
void jump2kernel(void)
{
#if CONFIG_KNL_EXRAM
sram_init();
sram_test();
// sram_test();
#endif
if (((*(__IO uint32_t *)KERNEL_IMG_START_ADDR) & 0x2FFE0000) == 0x20000000) // 检查栈顶地址是否合法,即检查此段Flash中是否已有APP程序
{
__set_PRIMASK(1);

View File

@@ -0,0 +1,7 @@
#pragma once
#include "u_types.h"
#include "u_rpc_svr.h"
#include "u_slist.h"
int net_drv_cli_write(obj_handler_t dm9000_obj, obj_handler_t shm_obj, int len);
int net_drv_cli_read(obj_handler_t dm9000_obj, obj_handler_t shm_obj);

View File

@@ -0,0 +1,8 @@
#pragma once
#include "u_types.h"
#include "u_rpc_svr.h"
#include "u_slist.h"
#include "net_drv_types.h"
int net_drv_write(obj_handler_t obj, int len);
int net_drv_read(obj_handler_t obj, int len);
void net_drv_init(net_drv_t *ns);

View File

@@ -0,0 +1,9 @@
#pragma once
#include "u_types.h"
#include "u_rpc_svr.h"
#include "u_slist.h"
typedef struct net_drv
{
rpc_svr_obj_t svr;
} net_drv_t;

View File

@@ -46,4 +46,8 @@
#define CONS_ACTIVE ((uint16_t)2) //!< console激活
#define PM_SIG_PROT 0x0007 //!< pm信号协议
#define PM_SIG_NOTIFY ((uint16_t)0) //!< 通知消息
#define PM_SIG_NOTIFY ((uint16_t)0) //!< 通知消息
#define NET_DRV_PROT 0x0008
#define NET_DRV_WRITE ((uint16_t)0) //!< 网络驱动写
#define NET_DRV_READ ((uint16_t)1) //!< 网络驱动读

View File

@@ -0,0 +1,45 @@
#include "rpc_prot.h"
#include "net_drv_cli.h"
#include "net_drv_types.h"
#include "u_rpc.h"
#include "u_rpc_svr.h"
#include "u_arch.h"
#include "u_rpc_buf.h"
#include "u_hd_man.h"
#include "u_rpc_buf.h"
#include <u_env.h>
#include <stdio.h>
RPC_GENERATION_CALL2(net_drv_t, NET_DRV_PROT, NET_DRV_WRITE, write,
rpc_obj_handler_t_t, rpc_obj_handler_t_t, RPC_DIR_IN, RPC_TYPE_BUF, shm_obj,
rpc_int_t, rpc_int_t, RPC_DIR_IN, RPC_TYPE_DATA, len)
RPC_GENERATION_CALL2(net_drv_t, NET_DRV_PROT, NET_DRV_READ, read,
rpc_obj_handler_t_t, rpc_obj_handler_t_t, RPC_DIR_IN, RPC_TYPE_BUF, shm_obj,
rpc_int_t, rpc_int_t, RPC_DIR_IN, RPC_TYPE_DATA, len)
int net_drv_cli_write(obj_handler_t dm9000_obj, obj_handler_t shm_obj, int len)
{
rpc_obj_handler_t_t rpc_hd = {
.data = shm_obj,
};
rpc_int_t rpc_len = {
.data = len,
};
msg_tag_t tag = net_drv_t_write_call(dm9000_obj, &rpc_hd, &rpc_len);
return msg_tag_get_val(tag);
}
int net_drv_cli_read(obj_handler_t dm9000_obj, obj_handler_t shm_obj)
{
rpc_obj_handler_t_t rpc_hd = {
.data = shm_obj,
};
rpc_int_t rpc_len = {
.data = 0,
};
msg_tag_t tag = net_drv_t_read_call(dm9000_obj, &rpc_hd, &rpc_len);
return msg_tag_get_val(tag);
}

View File

@@ -0,0 +1,37 @@
#include "rpc_prot.h"
#include "net_drv_svr.h"
#include "net_drv_types.h"
#include "u_rpc.h"
#include "u_rpc_svr.h"
#include "u_arch.h"
#include "u_rpc_buf.h"
#include "u_hd_man.h"
#include "u_rpc_buf.h"
#include <stdio.h>
RPC_GENERATION_OP2(net_drv_t, NET_DRV_PROT, NET_DRV_WRITE, write,
rpc_obj_handler_t_t, rpc_obj_handler_t_t, RPC_DIR_IN, RPC_TYPE_BUF, shm_obj,
rpc_int_t, rpc_int_t, RPC_DIR_IN, RPC_TYPE_DATA, len)
{
return net_drv_write(rpc_hd_get(0), len->data);
}
RPC_GENERATION_DISPATCH2(net_drv_t, NET_DRV_PROT, NET_DRV_WRITE, write,
rpc_obj_handler_t_t, rpc_obj_handler_t_t, RPC_DIR_IN, RPC_TYPE_BUF, svr_hd,
rpc_int_t, rpc_int_t, RPC_DIR_IN, RPC_TYPE_DATA, type)
RPC_GENERATION_OP2(net_drv_t, NET_DRV_PROT, NET_DRV_READ, read,
rpc_obj_handler_t_t, rpc_obj_handler_t_t, RPC_DIR_IN, RPC_TYPE_BUF, shm_obj,
rpc_int_t, rpc_int_t, RPC_DIR_IN, RPC_TYPE_DATA, len)
{
return net_drv_read(rpc_hd_get(0), len->data);
}
RPC_GENERATION_DISPATCH2(net_drv_t, NET_DRV_PROT, NET_DRV_READ, read,
rpc_obj_handler_t_t, rpc_obj_handler_t_t, RPC_DIR_IN, RPC_TYPE_BUF, shm_obj,
rpc_int_t, rpc_int_t, RPC_DIR_IN, RPC_TYPE_DATA, len)
RPC_DISPATCH2(net_drv_t, NET_DRV_PROT, typeof(NET_DRV_READ), NET_DRV_WRITE, write, NET_DRV_READ, read)
void net_drv_init(net_drv_t *ns)
{
rpc_svr_obj_init(&ns->svr, rpc_net_drv_t_dispatch, NET_DRV_PROT);
}

View File

@@ -15,10 +15,6 @@ int u_drv_init(void)
{
return msg_tag_get_val(tag);
}
tag = mm_align_alloc(MM_PROT, (void *)0x64000000, 0x1000000);
if (msg_tag_get_val(tag) < 0)
{
return msg_tag_get_val(tag);
}
return 0;
}

View File

@@ -42,11 +42,16 @@ int u_intr_bind(int irq_no, u_irq_prio_t prio, int th_prio,
handler_free_umap(irq_obj);
return ret;
}
if (irq)
{
*irq = irq_obj;
}
u_thread_run(th_hd, th_prio);
}
if (irq)
{
*irq = irq_obj;
}
return ret;
}

View File

@@ -3,3 +3,4 @@ cmake_minimum_required(VERSION 3.13)
# add_subdirectory(mr_drv)
# add_subdirectory(rtthread_drv)
add_subdirectory(dm9000_drv)

View File

@@ -0,0 +1,82 @@
cmake_minimum_required(VERSION 3.13)
file(GLOB_RECURSE deps *.c *.S)
file(GLOB bsp_src
${CMAKE_SOURCE_DIR}/mkrtos_bsp/STM32/STM32F10x_StdPeriph_Lib_V3.5.0/Libraries/STM32F10x_StdPeriph_Driver/src/*.c
)
list(APPEND deps ${bsp_src})
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DUSE_STDPERIPH_DRIVER=1 -DSTM32F10X_HD")
add_executable(dm9000_drv.elf
${deps}
)
target_link_libraries(dm9000_drv.elf
PUBLIC
start_tiny
printf
muslc
sys
sys_util
sys_svr
${GCC_LIB_PATH}/libgcc.a
)
target_include_directories(
dm9000_drv.elf
PUBLIC
${CMAKE_SOURCE_DIR}/mkrtos_user/lib/sys/inc
${CMAKE_SOURCE_DIR}/mkrtos_user/lib/sys_util/inc
${CMAKE_SOURCE_DIR}/mkrtos_user/lib/sys_svr/inc
${CMAKE_SOURCE_DIR}/mkrtos_user/lib/lwip/contrib/ports/mkrtos
${CMAKE_SOURCE_DIR}/mkrtos_user/lib/lwip/src/include
${CMAKE_SOURCE_DIR}/mkrtos_user/lib/lwip/src/include/lwip/apps
${CMAKE_SOURCE_DIR}/mkrtos_user/server/drv/dm9000_drv/inc
${CMAKE_SOURCE_DIR}/mkrtos_user/lib/printf/src/printf
${CMAKE_SOURCE_DIR}/mkrtos_user/lib/mlibc/arch/arm/
${CMAKE_SOURCE_DIR}/mkrtos_user/lib/mlibc/arch/generic
${CMAKE_SOURCE_DIR}/mkrtos_user/lib/mlibc/obj/src/internal
${CMAKE_SOURCE_DIR}/mkrtos_user/lib/mlibc/src/include
${CMAKE_SOURCE_DIR}/mkrtos_user/lib/mlibc/src/internal
${CMAKE_SOURCE_DIR}/mkrtos_user/lib/mlibc/obj/include
${CMAKE_SOURCE_DIR}/mkrtos_user/lib/mlibc/include
${CMAKE_SOURCE_DIR}/mkrtos_bsp/STM32/STM32F10x_StdPeriph_Lib_V3.5.0/Libraries/STM32F10x_StdPeriph_Driver/inc
${CMAKE_SOURCE_DIR}/mkrtos_bsp/STM32/STM32F10x_StdPeriph_Lib_V3.5.0/Libraries/CMSIS/Include
${CMAKE_SOURCE_DIR}/mkrtos_bsp/STM32/STM32F10x_StdPeriph_Lib_V3.5.0/Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x
${CMAKE_SOURCE_DIR}/mkrtos_bsp/STM32/STM32F10x_StdPeriph_Lib_V3.5.0/Libraries/CMSIS/CM3/CoreSupport
)
add_dependencies(dm9000_drv.elf
muslc
lwip
)
set_target_properties(dm9000_drv.elf PROPERTIES LINK_FLAGS
"-T ${CMAKE_CURRENT_LIST_DIR}/link.lds -pie --gc-section -no-dynamic-linker "
#--no-warn-rwx-segments
)
add_custom_target(
dm9000_drv_dump ALL
COMMAND
${CMAKE_SIZE} dm9000_drv.elf
COMMAND
${CMAKE_OBJCOPY} -O binary -S dm9000_drv.elf dm9000_drv.bin
COMMAND
mkdir -p ${CMAKE_SOURCE_DIR}/build/output/cpio
COMMAND
cp dm9000_drv.bin ${CMAKE_SOURCE_DIR}/build/output/cpio/dm9000_drv
COMMAND
cp dm9000_drv.elf ${CMAKE_SOURCE_DIR}/build/output/dm9000_drv.elf
)
add_dependencies(dm9000_drv_dump dm9000_drv.elf)
add_dependencies(dm9000_drv_dump sys)
add_dependencies(dm9000_drv_dump sys_util)
add_dependencies(dm9000_drv_dump mr)
add_dependencies(dm9000_drv_dump sys_svr)
add_dependencies(dm9000_drv_dump start_tiny)
add_dependencies(dm9000_drv_dump muslc)
add_dependencies(dm9000_drv_dump printf)

View File

@@ -0,0 +1,158 @@
#ifndef __DM9000_H
#define __DM9000_H
#include "mk_sys.h"
#include <stdint.h>
#include <stddef.h>
#include <pthread.h>
#include <semaphore.h>
#define DM9000_RST PGout(8) // DM9000复位引脚
#define DM9000_INT PFin(11) // DM9000中断引脚
// DM9000地址结构体
typedef struct
{
vu16 REG;
vu16 DATA;
} DM9000_TypeDef;
// 使用NOR/SRAM的 Bank1.sector2,地址位HADDR[27,26]=01 A7作为数据命令区分线
// 注意设置时STM32内部会右移一位对其!
#define DM9000_BASE ((volatile u32)(0x64000000 | 0x000000FE))
#define DM9000 ((DM9000_TypeDef *)DM9000_BASE)
#define DM9000_ID 0X90000A46 // DM9000 ID
#define DM9000_PKT_MAX 1536 // DM9000最大接收包长度
#define DM9000_PHY 0X40 // DM9000 PHY寄存器访问标志
// DM9000寄存器
#define DM9000_NCR 0X00
#define DM9000_NSR 0X01
#define DM9000_TCR 0X02
#define DM9000_TSRI 0X03
#define DM9000_TSRII 0X04
#define DM9000_RCR 0X05
#define DM9000_RSR 0X06
#define DM9000_ROCR 0X07
#define DM9000_BPTR 0X08
#define DM9000_FCTR 0X09
#define DM9000_FCR 0X0A
#define DM9000_EPCR 0X0B
#define DM9000_EPAR 0X0C
#define DM9000_EPDRL 0X0D
#define DM9000_EPDRH 0X0E
#define DM9000_WCR 0X0F
#define DM9000_PAR 0X10 // 物理地址0X10~0X15
#define DM9000_MAR 0X16 // 多播地址0X16~0X1D
#define DM9000_GPCR 0X1E
#define DM9000_GPR 0X1F
#define DM9000_TRPAL 0X22
#define DM9000_TRPAH 0X23
#define DM9000_RWPAL 0X24
#define DM9000_RWPAH 0X25
#define DM9000_VIDL 0X28
#define DM9000_VIDH 0X29
#define DM9000_PIDL 0X2A
#define DM9000_PIDH 0X2B
#define DM9000_CHIPR 0X2C
#define DM9000_TCR2 0X2D
#define DM9000_OCR 0X2E
#define DM9000_SMCR 0X2F
#define DM9000_ETXCSR 0X30
#define DM9000_TCSCR 0X31
#define DM9000_RCSCSR 0X32
#define DM9000_MRCMDX 0XF0
#define DM9000_MRCMDX1 0XF1
#define DM9000_MRCMD 0XF2
#define DM9000_MRRL 0XF4
#define DM9000_MRRH 0XF5
#define DM9000_MWCMDX 0XF6
#define DM9000_MWCMD 0XF8
#define DM9000_MWRL 0XFA
#define DM9000_MWRH 0XFB
#define DM9000_TXPLL 0XFC
#define DM9000_TXPLH 0XFD
#define DM9000_ISR 0XFE
#define DM9000_IMR 0XFF
#define NCR_RST 0X01
#define NSR_SPEED 0X80
#define NSR_LINKST 0X40
#define NSR_WAKEST 0X20
#define NSR_TX2END 0X08
#define NSR_TX1END 0X04
#define NSR_RXOV 0X02
#define RCR_DIS_LONG 0X20
#define RCR_DIS_CRC 0X10
#define RCR_ALL 0X08
#define RCR_RXEN 0X01
#define IMR_PAR 0X80
#define IMR_ROOI 0X08
#define IMR_POI 0X04 // 使能接收溢出中断
#define IMR_PTI 0X02 // 使能发送中断
#define IMR_PRI 0X01 // 使能接收中断
#define ISR_LNKCHGS (1 << 5)
#define ISR_ROOS (1 << 3)
#define ISR_ROS (1 << 2)
#define ISR_PTS (1 << 1)
#define ISR_PRS (1 << 0)
#define ISR_CLR_STATUS (ISR_ROOS | ISR_ROS | ISR_PTS | ISR_PRS)
// DM9000内部PHY寄存器
#define DM9000_PHY_BMCR 0X00
#define DM9000_PHY_BMSR 0X01
#define DM9000_PHY_PHYID1 0X02
#define DM9000_PHY_PHYID2 0X03
#define DM9000_PHY_ANAR 0X04
#define DM9000_PHY_ANLPAR 0X05
#define DM9000_PHY_ANER 0X06
#define DM9000_PHY_DSCR 0X10
#define DM9000_PHY_DSCSR 0X11
#define DM9000_PHY_10BTCSR 0X12
#define DM9000_PHY_PWDOR 0X13
#define DM9000_PHY_SCR 0X14
// DM9000工作模式定义
enum DM9000_PHY_mode
{
DM9000_10MHD = 0, // 10M半双工
DM9000_100MHD = 1, // 100M半双工
DM9000_10MFD = 4, // 10M全双工
DM9000_100MFD = 5, // 100M全双工
DM9000_AUTO = 8, // 自动协商
};
// DM9000配置结构体
struct dm9000_config
{
enum DM9000_PHY_mode mode; // 工作模式
u8 imr_all; // 中断类型
u16 queue_packet_len; // 每个数据包大小
u8 mac_addr[6]; // MAC地址
u8 multicase_addr[8]; // 组播地址
};
extern struct dm9000_config dm9000cfg; // dm9000配置结构体
#define DM9000_PACKET_BUF_SIZE 1526
extern uint8_t dm9000_packet_buf[DM9000_PACKET_BUF_SIZE];
extern int16_t dm9000_packet_len;
extern pthread_mutex_t dm9000lock; // DM9000读写互锁控制信号量
extern sem_t dm9000input; // DM9000接收数据信号量
u8 DM9000_Init(u8 mode);
u16 DM9000_ReadReg(u16 reg);
void DM9000_WriteReg(u16 reg, u16 data);
u16 DM9000_PHY_ReadReg(u16 reg);
void DM9000_PHY_WriteReg(u16 reg, u16 data);
u32 DM9000_Get_DeiviceID(void);
u8 DM9000_Get_SpeedAndDuplex(void);
void DM9000_Set_PHYMode(u8 mode);
void DM9000_Set_MACAddress(u8 *macaddr);
void DM9000_Set_Multicast(u8 *multicastaddr);
void DM9000_Reset(void);
void DM9000_SendPacket(const u8 *data, size_t len);
int DM9000_Receive_Packet(u8 *data, size_t len);
void DMA9000_ISRHandler(void);
#endif

View File

@@ -0,0 +1,65 @@
#pragma once
#include <stm32f10x.h>
#include <stm32f10x_conf.h>
// IO口操作宏定义
#define BITBAND(addr, bitnum) ((addr & 0xF0000000) + 0x2000000 + ((addr & 0xFFFFF) << 5) + (bitnum << 2))
#define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))
// IO口地址映射
#define GPIOA_ODR_Addr (GPIOA_BASE + 12) // 0x4001080C
#define GPIOB_ODR_Addr (GPIOB_BASE + 12) // 0x40010C0C
#define GPIOC_ODR_Addr (GPIOC_BASE + 12) // 0x4001100C
#define GPIOD_ODR_Addr (GPIOD_BASE + 12) // 0x4001140C
#define GPIOE_ODR_Addr (GPIOE_BASE + 12) // 0x4001180C
#define GPIOF_ODR_Addr (GPIOF_BASE + 12) // 0x40011A0C
#define GPIOG_ODR_Addr (GPIOG_BASE + 12) // 0x40011E0C
#define GPIOA_IDR_Addr (GPIOA_BASE + 8) // 0x40010808
#define GPIOB_IDR_Addr (GPIOB_BASE + 8) // 0x40010C08
#define GPIOC_IDR_Addr (GPIOC_BASE + 8) // 0x40011008
#define GPIOD_IDR_Addr (GPIOD_BASE + 8) // 0x40011408
#define GPIOE_IDR_Addr (GPIOE_BASE + 8) // 0x40011808
#define GPIOF_IDR_Addr (GPIOF_BASE + 8) // 0x40011A08
#define GPIOG_IDR_Addr (GPIOG_BASE + 8) // 0x40011E08
// IO口操作,只对单一的IO口!
// 确保n的值小于16!
#define PAout(n) BIT_ADDR(GPIOA_ODR_Addr, n) // 输出
#define PAin(n) BIT_ADDR(GPIOA_IDR_Addr, n) // 输入
#define PBout(n) BIT_ADDR(GPIOB_ODR_Addr, n) // 输出
#define PBin(n) BIT_ADDR(GPIOB_IDR_Addr, n) // 输入
#define PCout(n) BIT_ADDR(GPIOC_ODR_Addr, n) // 输出
#define PCin(n) BIT_ADDR(GPIOC_IDR_Addr, n) // 输入
#define PDout(n) BIT_ADDR(GPIOD_ODR_Addr, n) // 输出
#define PDin(n) BIT_ADDR(GPIOD_IDR_Addr, n) // 输入
#define PEout(n) BIT_ADDR(GPIOE_ODR_Addr, n) // 输出
#define PEin(n) BIT_ADDR(GPIOE_IDR_Addr, n) // 输入
#define PFout(n) BIT_ADDR(GPIOF_ODR_Addr, n) // 输出
#define PFin(n) BIT_ADDR(GPIOF_IDR_Addr, n) // 输入
#define PGout(n) BIT_ADDR(GPIOG_ODR_Addr, n) // 输出
#define PGin(n) BIT_ADDR(GPIOG_IDR_Addr, n) // 输入
// Ex_NVIC_Config专用定义
#define GPIO_A 0
#define GPIO_B 1
#define GPIO_C 2
#define GPIO_D 3
#define GPIO_E 4
#define GPIO_F 5
#define GPIO_G 6
#define FTIR 1 // 下降沿触发
#define RTIR 2 // 上升沿触发
// JTAG模式设置定义
#define JTAG_SWD_DISABLE 0X02
#define SWD_ENABLE 0X01
#define JTAG_SWD_ENABLE 0X00
void Ex_NVIC_Config(u8 GPIOx, u8 BITx, u8 TRIM);

View File

@@ -0,0 +1,77 @@
/**
******************************************************************************
* @file Project/STM32F10x_StdPeriph_Template/stm32f10x_conf.h
* @author MCD Application Team
* @version V3.5.0
* @date 08-April-2011
* @brief Library configuration file.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32F10x_CONF_H
#define __STM32F10x_CONF_H
/* Includes ------------------------------------------------------------------*/
/* Uncomment/Comment the line below to enable/disable peripheral header file inclusion */
#include "stm32f10x_adc.h"
#include "stm32f10x_bkp.h"
#include "stm32f10x_can.h"
#include "stm32f10x_cec.h"
#include "stm32f10x_crc.h"
#include "stm32f10x_dac.h"
#include "stm32f10x_dbgmcu.h"
#include "stm32f10x_dma.h"
#include "stm32f10x_exti.h"
#include "stm32f10x_flash.h"
#include "stm32f10x_fsmc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_i2c.h"
#include "stm32f10x_iwdg.h"
#include "stm32f10x_pwr.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_rtc.h"
#include "stm32f10x_sdio.h"
#include "stm32f10x_spi.h"
#include "stm32f10x_tim.h"
#include "stm32f10x_usart.h"
#include "stm32f10x_wwdg.h"
#include "misc.h" /* High level functions for NVIC and SysTick (add-on to CMSIS functions) */
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Uncomment the line below to expanse the "assert_param" macro in the
Standard Peripheral Library drivers code */
/* #define USE_FULL_ASSERT 1 */
/* Exported macro ------------------------------------------------------------*/
#ifdef USE_FULL_ASSERT
/**
* @brief The assert_param macro is used for function's parameters check.
* @param expr: If expr is false, it calls assert_failed function which reports
* the name of the source file and the source line number of the call
* that failed. If expr is true, it returns no value.
* @retval None
*/
#define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
/* Exported functions ------------------------------------------------------- */
void assert_failed(uint8_t* file, uint32_t line);
#else
#define assert_param(expr) ((void)0)
#endif /* USE_FULL_ASSERT */
#endif /* __STM32F10x_CONF_H */
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,119 @@
ENTRY(_start_)
SECTIONS
{
.text : {
. = ALIGN(4);
__text_start__ = .;
KEEP(*(.first))
*(.text)
*(.text.*)
KEEP(*(.init))
KEEP(*(.fini))
/* .ctors */
*crtbegin.o(.ctors)
*crtbegin?.o(.ctors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
*(SORT(.ctors.*))
*(.ctors)
/* .dtors */
*crtbegin.o(.dtors)
*crtbegin?.o(.dtors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
*(SORT(.dtors.*))
*(.dtors)
*(SORT(.rodata.*))
*(.rodata)
KEEP(*(.eh_frame*))
. = ALIGN(4);
__rel_start__ = .;
*(.rel.data .rel.data.* .rel.gnu.linkonce.d.*)
__rel_end__ = .;
}
.ARM.exidx : {
. = ALIGN(4);
__exdix_start = .;
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
/* This is used by the startup in order to initialize the .data secion */
__exdix_end = .;
}
.permissions_table : {
. = ALIGN(4);
__permissions_table_start__ = .;
KEEP(*(.permissions_table))
__permissions_table_end__ = .;
}
PROVIDE(__ram_size__ = __bss_end__ - __data_start__);
.data : {
. = ALIGN(4);
__data_start__ = .;
__got_start__ = .;
*(.got)
__got_end__ = .;
. = ALIGN(4);
*(.data)
*(.data.*)
*(vtable)
*(.data*)
. = ALIGN(4);
/* preinit data */
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP(*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
. = ALIGN(4);
/* init data */
PROVIDE_HIDDEN (__init_array_start = .);
KEEP(*(SORT(.init_array.*)))
KEEP(*(.init_array))
PROVIDE_HIDDEN (__init_array_end = .);
. = ALIGN(4);
/* finit data */
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP(*(SORT(.fini_array.*)))
KEEP(*(.fini_array))
PROVIDE_HIDDEN (__fini_array_end = .);
. = ALIGN(4);
/* All data end */
__data_end__ = .;
}
PROVIDE(__heap_size__ = __heap_end__ - __heap_start__);
PROVIDE(__stack_size__ = __stack_end__ - __stack_start__);
.bss : {
. = ALIGN(4);
/* This is used by the startup in order to initialize the .bss secion */
__bss_start__ = .;
*(.bss)
*(COMMON)
. = ALIGN(4);
__heap_start__ = .;
KEEP(*(.bss.heap))
__heap_end__ = .;
. = ALIGN(4);
__stack_start__ = .;
KEEP(*(.bss.stack))
__stack_end__ = .;
*(.bss.*)
/* This is used by the startup in order to initialize the .bss secion */
. = ALIGN(4);
__bss_end__ = .;
}
_end = .;
}

View File

@@ -0,0 +1,477 @@
#include "dm9000.h"
#include <u_intr.h>
#include <u_sleep.h>
#include <pthread.h>
#include <assert.h>
#include <semaphore.h>
#include <printf.h>
struct dm9000_config dm9000cfg; // DM9000配置结构体
sem_t dm9000input; // DM9000接收数据信号量
pthread_mutex_t dm9000lock; // DM9000读写互锁控制信号量
obj_handler_t irq_obj;
// #define DM9000_PACKET_BUF_SIZE 1526
// uint8_t dm9000_packet_buf[DM9000_PACKET_BUF_SIZE];
// int16_t dm9000_packet_len = 0;
#define IRQ_THREAD_PRIO 3
#define STACK_SIZE (512 + 128)
static __attribute__((aligned(8))) uint8_t stack0[STACK_SIZE];
static uint8_t msg_buf[128];
void EXTI15_10_IRQHandler(void);
// 初始化DM9000
// mode:0,仅仅读DM9000的ID,看能否读到ID.
// 1,完全初始化,正常应用时使用
// 返回值:
// 0,初始化成功
// 1DM9000A ID读取错误
u8 DM9000_Init(u8 mode)
{
u32 temp;
sem_init(&dm9000input, 0, 0);
pthread_mutex_init(&dm9000lock, NULL);
// 先初始化和DM9000连接的IO和FSMC
RCC->AHBENR |= 1 << 8; // 使能FSMC时钟
RCC->APB2ENR |= 1 << 5; // 使能PORTD时钟
RCC->APB2ENR |= 1 << 6; // 使能PORTE时钟
RCC->APB2ENR |= 1 << 7; // 使能PORTF时钟
RCC->APB2ENR |= 1 << 8; // 使能PORTG时钟
// PORTD复用推挽输出
GPIOD->CRH = (GPIOD->CRH & 0X00FFF000) | 0XBB000BBB;
GPIOD->CRL = (GPIOD->CRH & 0XFF00FF00) | 0X00BB00BB;
// PORTE复用推挽输出
GPIOE->CRH = (GPIOE->CRH & 0X00000000) | 0XBBBBBBBB;
GPIOE->CRL = (GPIOE->CRL & 0X0FFFFFFF) | 0XB0000000;
// PORTF复用推挽输出 PF13-->FSMC_A7 PF11 DM9000中断输入,上拉
GPIOF->CRH = (GPIOF->CRH & 0XFF0F0FFF) | 0X00B08000;
// PORTG复用推挽输出 PG9->NE2 PG8 推挽输出--> DM9000_RST
GPIOG->CRH = (GPIOG->CRH & 0XFFFFFF00) | 0X000000B3;
GPIOF->ODR |= 1 << 11; // PF11 上拉
Ex_NVIC_Config(GPIO_F, 11, FTIR); // 下降沿触发
assert(u_intr_bind(EXTI15_10_IRQn, u_irq_prio_create(1, 0), IRQ_THREAD_PRIO,
stack0 + STACK_SIZE, msg_buf, EXTI15_10_IRQHandler, &irq_obj) >= 0);
// 寄存器清零
// bank1有NE1~4,每一个有一个BCR+TCR所以总共八个寄存器。
// 这里我们使用NE2 也就对应BTCR[2],[3]。
FSMC_Bank1->BTCR[2] = 0X00000000;
FSMC_Bank1->BTCR[3] = 0X00000000;
FSMC_Bank1E->BWTR[2] = 0X00000000;
// 操作BCR寄存器 使用异步模式,模式A(读写共用一个时序寄存器)
// BTCR[偶数]:BCR寄存器;BTCR[奇数]:BTR寄存器
FSMC_Bank1->BTCR[2] |= 1 << 12; // 存储器写使能
FSMC_Bank1->BTCR[2] |= 1 << 4; // 存储器数据宽度为16bit
// 操作BTR寄存器
FSMC_Bank1->BTCR[3] |= 3 << 8; // 数据保持时间DATAST为3个HCLK 4/72M=55ns(对DM9000芯片)
FSMC_Bank1->BTCR[3] |= 0 << 4; // 地址保持时间ADDHLD未用到
FSMC_Bank1->BTCR[3] |= 1 << 0; // 地址建立时间ADDSET为2个HCLK 2/72M=27ns
// 闪存写时序寄存器
FSMC_Bank1E->BWTR[2] = 0x0FFFFFFF; // 默认值
// 使能BANK1区域2
FSMC_Bank1->BTCR[2] |= 1 << 0;
temp = *(vu32 *)(0x1FFFF7E8); // 获取STM32的唯一ID的前24位作为MAC地址后三字节
dm9000cfg.mode = DM9000_AUTO;
dm9000cfg.queue_packet_len = 0;
// DM9000的SRAM的发送和接收指针自动返回到开始地址并且开启接收中断
dm9000cfg.imr_all = IMR_PAR | IMR_PRI;
// 初始化MAC地址
dm9000cfg.mac_addr[0] = 2;
dm9000cfg.mac_addr[1] = 0;
dm9000cfg.mac_addr[2] = 0;
dm9000cfg.mac_addr[3] = (temp >> 16) & 0XFF; // 低三字节用STM32的唯一ID
dm9000cfg.mac_addr[4] = (temp >> 8) & 0XFFF;
dm9000cfg.mac_addr[5] = temp & 0XFF;
// 初始化组播地址
dm9000cfg.multicase_addr[0] = 0Xff;
dm9000cfg.multicase_addr[1] = 0Xff;
dm9000cfg.multicase_addr[2] = 0Xff;
dm9000cfg.multicase_addr[3] = 0Xff;
dm9000cfg.multicase_addr[4] = 0Xff;
dm9000cfg.multicase_addr[5] = 0Xff;
dm9000cfg.multicase_addr[6] = 0Xff;
dm9000cfg.multicase_addr[7] = 0Xff;
DM9000_Reset(); // 复位DM9000
u_sleep_ms(100);
temp = DM9000_Get_DeiviceID(); // 获取DM9000ID
// mk_printf("DM9000 ID:%#x\r\n",temp);
if (temp != DM9000_ID)
return 1; // 读取ID错误
if (mode == 0)
return 0; // 仅仅读ID,任务完成
DM9000_Set_PHYMode(dm9000cfg.mode); // 设置PHY工作模式
DM9000_WriteReg(DM9000_NCR, 0X00);
DM9000_WriteReg(DM9000_TCR, 0X00); // 发送控制寄存器清零
DM9000_WriteReg(DM9000_BPTR, 0X3F);
DM9000_WriteReg(DM9000_FCTR, 0X38);
DM9000_WriteReg(DM9000_FCR, 0X00);
DM9000_WriteReg(DM9000_SMCR, 0X00); // 特殊模式
DM9000_WriteReg(DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END); // 清除发送状态
DM9000_WriteReg(DM9000_ISR, 0X0F); // 清除中断状态
DM9000_WriteReg(DM9000_TCR2, 0X80); // 切换LED到mode1
// 设置MAC地址和组播地址
DM9000_Set_MACAddress(dm9000cfg.mac_addr); // 设置MAC地址
DM9000_Set_Multicast(dm9000cfg.multicase_addr); // 设置组播地址
DM9000_WriteReg(DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN);
DM9000_WriteReg(DM9000_IMR, IMR_PAR);
temp = DM9000_Get_SpeedAndDuplex(); // 获取DM9000的连接速度和双工状态
if (temp != 0XFF) // 连接成功,通过串口显示连接速度和双工状态
{
mk_printf("DM9000 Speed:%dMbps,Duplex:%s duplex mode\r\n", (temp & 0x02) ? 10 : 100, (temp & 0x01) ? "Full" : "Half");
}
// else mk_printf("DM9000 Establish Link Failed!\r\n");
DM9000_WriteReg(DM9000_IMR, dm9000cfg.imr_all); // 设置中断
return 0;
}
// 读取DM9000指定寄存器的值
// reg:寄存器地址
// 返回值DM9000指定寄存器的值
u16 DM9000_ReadReg(u16 reg)
{
DM9000->REG = reg;
return DM9000->DATA;
}
// 向DM9000指定寄存器中写入指定值
// reg:要写入的寄存器
// data:要写入的值
void DM9000_WriteReg(u16 reg, u16 data)
{
DM9000->REG = reg;
DM9000->DATA = data;
}
// 读取DM9000的PHY的指定寄存器
// reg:要读的PHY寄存器
// 返回值:读取到的PHY寄存器值
u16 DM9000_PHY_ReadReg(u16 reg)
{
u16 temp;
DM9000_WriteReg(DM9000_EPAR, DM9000_PHY | reg);
DM9000_WriteReg(DM9000_EPCR, 0X0C); // 选中PHY发送读命令
u_sleep_ms(10);
DM9000_WriteReg(DM9000_EPCR, 0X00); // 清除读命令
temp = (DM9000_ReadReg(DM9000_EPDRH) << 8) | (DM9000_ReadReg(DM9000_EPDRL));
return temp;
}
// 向DM9000的PHY寄存器写入指定值
// reg:PHY寄存器
// data:要写入的值
void DM9000_PHY_WriteReg(u16 reg, u16 data)
{
DM9000_WriteReg(DM9000_EPAR, DM9000_PHY | reg);
DM9000_WriteReg(DM9000_EPDRL, (data & 0xff)); // 写入低字节
DM9000_WriteReg(DM9000_EPDRH, ((data >> 8) & 0xff)); // 写入高字节
DM9000_WriteReg(DM9000_EPCR, 0X0A); // 选中PHY,发送写命令
u_sleep_ms(50);
DM9000_WriteReg(DM9000_EPCR, 0X00); // 清除写命令
}
// 获取DM9000的芯片ID
// 返回值DM9000的芯片ID值
u32 DM9000_Get_DeiviceID(void)
{
u32 value;
value = DM9000_ReadReg(DM9000_VIDL);
value |= DM9000_ReadReg(DM9000_VIDH) << 8;
value |= DM9000_ReadReg(DM9000_PIDL) << 16;
value |= DM9000_ReadReg(DM9000_PIDH) << 24;
return value;
}
// 获取DM9000的连接速度和双工模式
// 返回值: 0,100M半双工
// 1,100M全双工
// 2,10M半双工
// 3,10M全双工
// 0XFF,连接失败!
u8 DM9000_Get_SpeedAndDuplex(void)
{
u8 temp;
u8 i = 0;
if (dm9000cfg.mode == DM9000_AUTO) // 如果开启了自动协商模式一定要等待协商完成
{
while (!(DM9000_PHY_ReadReg(0X01) & 0X0020)) // 等待自动协商完成
{
u_sleep_ms(100);
i++;
if (i > 100)
return 0XFF; // 自动协商失败
}
}
else // 自定义模式,一定要等待连接成功
{
while (!(DM9000_ReadReg(DM9000_NSR) & 0X40)) // 等待连接成功
{
u_sleep_ms(100);
i++;
if (i > 100)
return 0XFF; // 连接失败
}
}
temp = ((DM9000_ReadReg(DM9000_NSR) >> 6) & 0X02); // 获取DM9000的连接速度
temp |= ((DM9000_ReadReg(DM9000_NCR) >> 3) & 0X01); // 获取DM9000的双工状态
return temp;
}
// 设置DM900的PHY工作模式
// mode:PHY模式
void DM9000_Set_PHYMode(u8 mode)
{
u16 BMCR_Value, ANAR_Value;
switch (mode)
{
case DM9000_10MHD: // 10M半双工
BMCR_Value = 0X0000;
ANAR_Value = 0X21;
break;
case DM9000_10MFD: // 10M全双工
BMCR_Value = 0X0100;
ANAR_Value = 0X41;
break;
case DM9000_100MHD: // 100M半双工
BMCR_Value = 0X2000;
ANAR_Value = 0X81;
break;
case DM9000_100MFD: // 100M全双工
BMCR_Value = 0X2100;
ANAR_Value = 0X101;
break;
case DM9000_AUTO: // 自动协商模式
BMCR_Value = 0X1000;
ANAR_Value = 0X01E1;
break;
}
DM9000_PHY_WriteReg(DM9000_PHY_BMCR, BMCR_Value);
DM9000_PHY_WriteReg(DM9000_PHY_ANAR, ANAR_Value);
DM9000_WriteReg(DM9000_GPR, 0X00); // 使能PHY
}
// 设置DM9000的MAC地址
// macaddr:指向MAC地址
void DM9000_Set_MACAddress(u8 *macaddr)
{
u8 i;
for (i = 0; i < 6; i++)
{
DM9000_WriteReg(DM9000_PAR + i, macaddr[i]);
}
}
// 设置DM9000的组播地址
// multicastaddr:指向多播地址
void DM9000_Set_Multicast(u8 *multicastaddr)
{
u8 i;
for (i = 0; i < 8; i++)
{
DM9000_WriteReg(DM9000_MAR + i, multicastaddr[i]);
}
}
// 复位DM9000
void DM9000_Reset(void)
{
// 复位DM9000,复位步骤参考<DM9000 Application Notes V1.22>手册29页
DM9000_RST = 0; // DM9000硬件复位
u_sleep_ms(10);
DM9000_RST = 1; // DM9000硬件复位结束
u_sleep_ms(100); // 一定要有这个延时让DM9000准备就绪
DM9000_WriteReg(DM9000_GPCR, 0x01); // 第一步:设置GPCR寄存器(0X1E)的bit0为1
DM9000_WriteReg(DM9000_GPR, 0); // 第二步:设置GPR寄存器(0X1F)的bit1为0DM9000内部的PHY上电
DM9000_WriteReg(DM9000_NCR, (0x02 | NCR_RST)); // 第三步:软件复位DM9000
do
{
u_sleep_ms(25);
} while (DM9000_ReadReg(DM9000_NCR) & 1); // 等待DM9000软复位完成
DM9000_WriteReg(DM9000_NCR, 0);
DM9000_WriteReg(DM9000_NCR, (0x02 | NCR_RST)); // DM9000第二次软复位
do
{
u_sleep_ms(25);
} while (DM9000_ReadReg(DM9000_NCR) & 1);
}
// 通过DM9000发送数据包
// p:pbuf结构体指针
void DM9000_SendPacket(const u8 *data, size_t len)
{
u16 pbuf_index = 0;
u8 word[2], word_index = 0;
u8 err;
// mk_printf("send len:%d\r\n",p->tot_len);
pthread_mutex_lock(&dm9000lock); // 请求互斥信号量,锁定DM9000
DM9000_WriteReg(DM9000_IMR, IMR_PAR); // 关闭网卡中断
DM9000->REG = DM9000_MWCMD; // 发送此命令后就可以将要发送的数据搬到DM9000 TX SRAM中
// 向DM9000的TX SRAM中写入数据一次写入两个字节数据
// 当要发送的数据长度为奇数的时候我们需要将最后一个字节单独写入DM9000的TX SRAM中
while (1)
{
if (pbuf_index < len)
{
word[word_index++] = ((u8 *)data)[pbuf_index++];
if (word_index == 2)
{
DM9000->DATA = ((u16)word[1] << 8) | word[0];
word_index = 0;
}
}
else
{
pbuf_index = 0;
break;
}
}
// 还有一个字节未写入TX SRAM
if (word_index == 1)
DM9000->DATA = word[0];
// 向DM9000写入发送长度
DM9000_WriteReg(DM9000_TXPLL, len & 0XFF);
DM9000_WriteReg(DM9000_TXPLH, (len >> 8) & 0XFF); // 设置要发送数据的数据长度
DM9000_WriteReg(DM9000_TCR, 0X01); // 启动发送
while ((DM9000_ReadReg(DM9000_ISR) & 0X02) == 0)
; // 等待发送完成
DM9000_WriteReg(DM9000_ISR, 0X02); // 清除发送完成中断
DM9000_WriteReg(DM9000_IMR, dm9000cfg.imr_all); // DM9000网卡接收中断使能
// DM9000_WriteReg(DM9000_IMR,IMR_POI|IMR_PTI|IMR_PRI); //DM9000网卡接收中断使能
pthread_mutex_unlock(&dm9000lock); // 发送互斥信号量,解锁DM9000
}
// DM9000接收数据包
// 接收到的数据包存放在DM9000的RX FIFO中地址为0X0C00~0X3FFF
// 接收到的数据包的前四个字节并不是真实的数据,而是有特定含义的
// byte1:表明是否接收到数据为0x00或者0X01如果两个都不是的话一定要软件复位DM9000
// 0x01接收到数据
// 0x00未接收到数据
// byte2:第二个字节表示一些状态信息和DM9000的RSR(0X06)寄存器一致的
// byte3:本帧数据长度的低字节
// byte4:本帧数据长度的高字节
// 返回值pbuf格式的接收到的数据包
int DM9000_Receive_Packet(u8 *recv_data, size_t len)
{
struct pbuf *p;
struct pbuf *q;
u32 rxbyte;
vu16 rx_status, rx_length;
u16 *data;
u16 dummy;
int tm_len;
u8 err;
int ret = -1;
p = NULL;
pthread_mutex_lock(&dm9000lock); // 请求互斥信号量,锁定DM9000
__error_retry:
DM9000_ReadReg(DM9000_MRCMDX); // 假读
rxbyte = (u8)DM9000->DATA; // 进行第二次读取
if (rxbyte) // 接收到数据
{
if (rxbyte > 1) // rxbyte大于1接收到的数据错误,挂了
{
mk_printf("dm9000 rx: rx error, stop device\r\n");
DM9000_WriteReg(DM9000_RCR, 0x00);
DM9000_WriteReg(DM9000_ISR, 0x80);
pthread_mutex_unlock(&dm9000lock); // 发送互斥信号量,解锁DM9000
return -1;
}
DM9000->REG = DM9000_MRCMD;
rx_status = DM9000->DATA;
rx_length = DM9000->DATA;
if (rx_length <= len)
{
// if(rx_length>512)mk_printf("rxlen:%d\r\n",rx_length);
for (size_t i = 0; i < rx_length; i += 2)
{
((u16 *)recv_data)[i / 2] = DM9000->DATA;
}
ret = rx_length;
}
else // 内存申请失败
{
mk_printf("缓存大小不足:%d\r\n", rx_length);
data = &dummy;
tm_len = rx_length;
while (tm_len)
{
*data = DM9000->DATA;
tm_len -= 2;
}
ret = -1;
}
// 根据rx_status判断接收数据是否出现如下错误FIFO溢出、CRC错误
// 对齐错误、物理层错误,如果有任何一个出现的话丢弃该数据帧,
// 当rx_length小于64或者大于最大数据长度的时候也丢弃该数据帧
if ((rx_status & 0XBF00) || (rx_length < 0X40) || (rx_length > DM9000_PKT_MAX))
{
mk_printf("rx_status:%#x\r\n", rx_status);
if (rx_status & 0x100)
mk_printf("rx fifo error\r\n");
if (rx_status & 0x200)
mk_printf("rx crc error\r\n");
if (rx_status & 0x8000)
mk_printf("rx length error\r\n");
if (rx_length > DM9000_PKT_MAX)
{
mk_printf("rx length too big\r\n");
DM9000_WriteReg(DM9000_NCR, NCR_RST); // 复位DM9000
u_sleep_ms(5);
}
// if (p != NULL)
// pbuf_free((struct pbuf *)p); // 释放内存
// p = NULL;
goto __error_retry;
}
}
else
{
DM9000_WriteReg(DM9000_ISR, ISR_PTS); // 清除所有中断标志位
dm9000cfg.imr_all = IMR_PAR | IMR_PRI; // 重新接收中断
DM9000_WriteReg(DM9000_IMR, dm9000cfg.imr_all);
}
pthread_mutex_unlock(&dm9000lock); // 发送互斥信号量,解锁DM9000
return ret;
}
// 中断处理函数
void DMA9000_ISRHandler(void)
{
u16 int_status;
u16 last_io;
last_io = DM9000->REG;
int_status = DM9000_ReadReg(DM9000_ISR);
DM9000_WriteReg(DM9000_ISR, int_status); // 清除中断标志位DM9000的ISR寄存器的bit0~bit5写1清零
// if(int_status & ISR_ROS)mk_printf("overflow \r\n");
// if(int_status & ISR_ROOS)mk_printf("overflow counter overflow \r\n");
if (int_status & ISR_PRS) // 接收中断
{
sem_post(&dm9000input); // 处理接收到数据帧
}
if (int_status & ISR_PTS) // 发送中断
{
// 接收中断处理,这里没用到
}
DM9000->REG = last_io;
}
// 外部中断5~9服务程序
void EXTI15_10_IRQHandler(void)
{
while (1)
{
msg_tag_t tag = uirq_wait(irq_obj, 0);
if (msg_tag_get_val(tag) >= 0)
{
if (EXTI_GetITStatus(EXTI_Line11) != RESET)
{
EXTI_ClearITPendingBit(EXTI_Line11);
while (DM9000_INT == 0)
{
DMA9000_ISRHandler();
}
}
}
uirq_ack(irq_obj, EXTI15_10_IRQn);
}
}

View File

@@ -0,0 +1,17 @@
#define HEAP_SIZE 2048
#define STACK_SIZE (1024 + 256)
#if defined(__CC_ARM)
#define HEAP_ATTR SECTION("HEAP") __attribute__((zero_init))
#define STACK_ATTR SECTION("STACK") __attribute__((zero_init))
#elif defined(__GNUC__)
#define HEAP_ATTR __attribute__((__section__(".bss.heap")))
#define STACK_ATTR __attribute__((__section__(".bss.stack")))
#elif defined(__IAR_SYSTEMS_ICC__)
#define HEAP_ATTR
#define STACK_ATTR
#endif
__attribute__((used)) HEAP_ATTR static char heap[HEAP_SIZE];
__attribute__((used)) STACK_ATTR static char stack[STACK_SIZE];

View File

@@ -0,0 +1,80 @@
#include <printf.h>
#include <assert.h>
#include <u_drv.h>
#include <u_prot.h>
#include <u_mm.h>
#include "dm9000.h"
#include <u_thread.h>
#include <pthread.h>
#include <u_rpc_svr.h>
#include <u_hd_man.h>
#include <net_drv_svr.h>
#include <u_share_mem.h>
#include <rpc_prot.h>
#include <ns_cli.h>
int net_drv_write(obj_handler_t obj, int len)
{
int ret = -1;
addr_t addr = 0;
umword_t size = 0;
msg_tag_t tag = share_mem_map(obj, 3, &addr, &size);
if (msg_tag_get_val(tag) < 0)
{
handler_free_umap(obj);
mk_printf("net write error.\n");
return msg_tag_get_val(tag);
}
DM9000_SendPacket((uint8_t *)addr, MIN(size, len));
// mk_printf("net write len:%d.\n", MIN(size, len));
handler_free_umap(obj);
return len;
}
int net_drv_read(obj_handler_t obj, int len)
{
int ret = -1;
addr_t addr = 0;
umword_t size = 0;
msg_tag_t tag = share_mem_map(obj, 3, &addr, &size);
uint32_t _err;
// _err = sem_wait(&dm9000input); // 请求信号量
// if (_err == 0)
// {
ret = DM9000_Receive_Packet((uint8_t *)addr, size);
if (ret >= 0)
{
// mk_printf("net read len:%d.\n", ret);
}
// }
handler_free_umap(obj);
return ret;
}
static net_drv_t net_drv;
int main(int argc, char *args[])
{
msg_tag_t tag;
obj_handler_t hd;
int ret;
u_drv_init();
tag = mm_align_alloc(MM_PROT, (void *)0x64000000, 0x1000000);
assert(msg_tag_get_val(tag) >= 0);
net_drv_init(&net_drv);
ret = rpc_meta_init(THREAD_MAIN, &hd);
assert(ret >= 0);
meta_reg_svr_obj(&net_drv.svr, NET_DRV_PROT);
ns_register("/dm9000", hd, MOUNT_NODE);
mk_printf("dm9000 reg success\n");
DM9000_Init(1);
rpc_loop();
while (1)
{
// never run this.
}
return 0;
}

View File

@@ -0,0 +1,27 @@
#include "mk_sys.h"
// 外部中断配置函数
// 只针对GPIOA~G;不包括PVD,RTC和USB唤醒这三个
// 参数:
// GPIOx:0~6,代表GPIOA~G
// BITx:需要使能的位;
// TRIM:触发模式,1,下升沿;2,上降沿;3任意电平触发
// 该函数一次只能配置1个IO口,多个IO口,需多次调用
// 该函数会自动开启对应中断,以及屏蔽线
void Ex_NVIC_Config(u8 GPIOx, u8 BITx, u8 TRIM)
{
u8 EXTADDR;
u8 EXTOFFSET;
EXTADDR = BITx / 4; // 得到中断寄存器组的编号
EXTOFFSET = (BITx % 4) * 4;
RCC->APB2ENR |= 0x01; // 使能io复用时钟
AFIO->EXTICR[EXTADDR] &= ~(0x000F << EXTOFFSET); // 清除原来设置!!!
AFIO->EXTICR[EXTADDR] |= GPIOx << EXTOFFSET; // EXTI.BITx映射到GPIOx.BITx
// 自动设置
EXTI->IMR |= 1 << BITx; // 开启line BITx上的中断
// EXTI->EMR|=1<<BITx;//不屏蔽line BITx上的事件 (如果不屏蔽这句,在硬件上是可以的,但是在软件仿真的时候无法进入中断!)
if (TRIM & 0x01)
EXTI->FTSR |= 1 << BITx; // line BITx上事件下降沿触发
if (TRIM & 0x02)
EXTI->RTSR |= 1 << BITx; // line BITx上事件上升降沿触发
}

View File

@@ -1,6 +1,7 @@
#一次读取一行,每行代表启动的应用程序,暂时不支持参数
# fatfs
cpiofs
net
# cpiofs
# dm9000_drv
# net
sh

View File

@@ -601,11 +601,11 @@ int namespace_query(const char *path, obj_handler_t *hd)
ns_unlock();
return -EEXIST;
}
if (node && ret_inx == strlen(path))
{
ns_unlock();
return -EEXIST;
}
// if (ret_inx == strlen(path))
// {
// ns_unlock();
// return -EEXIST;
// }
if (node->type == DIR_NODE)
{
ns_unlock();

View File

@@ -17,3 +17,4 @@
#define MAC_ADDR5 9
void net_init(void);
void LwIP_Pkt_Handle(void);
void lwip_pkt_handle_raw(uint8_t *data, int len);

View File

@@ -81,7 +81,7 @@ u8 DM9000_Init(u8 mode)
dm9000cfg.mac_addr[1] = 0;
dm9000cfg.mac_addr[2] = 0;
dm9000cfg.mac_addr[3] = (temp >> 16) & 0XFF; // 低三字节用STM32的唯一ID
dm9000cfg.mac_addr[4] = (temp >> 8) & 0XFFF;
dm9000cfg.mac_addr[4] = (temp >> 8) & 0XFF;
dm9000cfg.mac_addr[5] = temp & 0XFF;
// 初始化组播地址
dm9000cfg.multicase_addr[0] = 0Xff;

View File

@@ -10,10 +10,20 @@
#include <pthread.h>
#include <cons_cli.h>
#include "dm9000.h"
extern sem_t dm9000input; // DM9000接收数据信号量
#include <net_drv_cli.h>
#include <u_hd_man.h>
#include <u_factory.h>
#include <u_share_mem.h>
#include <u_task.h>
#include <ns_cli.h>
#include <assert.h>
static obj_handler_t net_drv_hd;
extern sem_t dm9000input; // DM9000接收数据信号量
extern pthread_mutex_t dm9000lock; // DM9000读写互锁控制信号量
/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */
obj_handler_t send_shm_hd;
umword_t send_shm_addr;
umword_t send_shm_size;
#define IFNAME0 'e'
#define IFNAME1 'n'
@@ -23,17 +33,29 @@ extern pthread_mutex_t dm9000lock; // DM9000读写互锁控制信号量
// 其他,失败
static err_t low_level_init(struct netif *netif)
{
umword_t tmp = *(vu32 *)(0x1FFFF7E8);
// INT8U err;
netif->hwaddr_len = ETHARP_HWADDR_LEN; // 设置MAC地址长度,为6个字节
// 初始化MAC地址,设置什么地址由用户自己设置,但是不能与网络中其他设备MAC地址重复
netif->hwaddr[0] = dm9000cfg.mac_addr[0];
netif->hwaddr[1] = dm9000cfg.mac_addr[1];
netif->hwaddr[2] = dm9000cfg.mac_addr[2];
netif->hwaddr[3] = dm9000cfg.mac_addr[3];
netif->hwaddr[4] = dm9000cfg.mac_addr[4];
netif->hwaddr[5] = dm9000cfg.mac_addr[5];
netif->hwaddr[0] = 2;
netif->hwaddr[1] = 0;
netif->hwaddr[2] = 0;
netif->hwaddr[3] = (tmp >> 16) & 0XFF; // 低三字节用STM32的唯一ID
netif->hwaddr[4] = (tmp >> 8) & 0XFF;
netif->hwaddr[5] = tmp & 0XFF;
netif->mtu = 1500; // 最大允许传输单元,允许该网卡广播和ARP功能
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
assert(ns_query("/dm9000", &net_drv_hd) >= 0);
msg_tag_t tag;
send_shm_hd = handler_alloc();
assert(send_shm_hd != HANDLER_INVALID);
tag = facotry_create_share_mem(FACTORY_PROT, vpage_create_raw3(KOBJ_ALL_RIGHTS, 0, send_shm_hd), 2048);
assert(msg_tag_get_prot(tag) >= 0);
tag = share_mem_map(send_shm_hd, 3, &send_shm_addr, &send_shm_size);
assert(msg_tag_get_prot(tag) >= 0);
return ERR_OK;
}
// 用于发送数据包的最底层函数(lwip通过netif->linkoutput指向该函数)
@@ -43,8 +65,11 @@ static err_t low_level_init(struct netif *netif)
// ERR_MEM,发送失败
static err_t low_level_output(struct netif *netif, struct pbuf *p)
{
DM9000_SendPacket(p); // 发送数据
return ERR_OK;
int ret;
// DM9000_SendPacket(p); // 发送数据
memcpy((void *)send_shm_addr, p->payload, p->len);
ret = net_drv_cli_write(net_drv_hd, send_shm_hd, p->len);
return ret >= 0 ? ERR_OK : ERR_IF;
}
// 用于接收数据包的最底层函数
// neitif:网卡结构体指针
@@ -85,6 +110,25 @@ err_t ethernetif_input(struct netif *netif)
}
}
}
err_t ethernetif_input_raw(struct netif *netif, uint8_t *data, int len)
{
err_t err = ERR_MEM;
struct pbuf *p;
p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); // pbufs内存池分配pbuf
if (p != NULL) // 内存申请成功
{
memcpy(p->payload, data, len);
err = netif->input(p, netif); // 调用netif结构体中的input字段(一个函数)来处理数据包
if (err != ERR_OK)
{
LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
pbuf_free(p);
p = NULL;
}
}
return err;
}
// static void arp_timer(void *arg);
// 使用low_level_init()函数来初始化网络
// netif:网卡结构体指针

View File

@@ -9,28 +9,63 @@
#include "libc.h"
#include "dm9000.h"
#include "lwiperf.h"
#include "u_prot.h"
#include "u_mm.h"
#include <u_hd_man.h>
#include <u_task.h>
#include <u_factory.h>
#include <u_share_mem.h>
#include <net_drv_cli.h>
#include <ns_cli.h>
umword_t addr;
umword_t size;
obj_handler_t net_drv_hd;
extern void EXTI15_10_IRQHandler(void);
int main(int args, char *argv[])
{
struct __libc *lc = &libc;
int ret;
msg_tag_t tag;
// struct __libc *lc = &libc;
// printf("libc:0x%x\n", lc);
printf("libc:0x%x\n", lc);
assert(u_drv_init() >= 0);
tag = mm_align_alloc(MM_PROT, (void *)0x64000000, 0x1000000);
assert(msg_tag_get_val(tag) >= 0);
cons_write_str("net init..\n");
if (DM9000_Init(1))
{
cons_write_str("err.\n");
return 2; // 初始化DM9000AEP
}
// if (DM9000_Init(1))
// {
// cons_write_str("err.\n");
// return 2; // 初始化DM9000AEP
// }
net_init();
cons_write_str("net start success..\n");
ip_addr_t perf_server_ip;
IP_ADDR4(&perf_server_ip, 192, 168, 3, 10);
lwiperf_start_tcp_server(&perf_server_ip, 9527, NULL, NULL);
obj_handler_t shm_hd = handler_alloc();
assert(shm_hd != HANDLER_INVALID);
tag = facotry_create_share_mem(FACTORY_PROT, vpage_create_raw3(KOBJ_ALL_RIGHTS, 0, shm_hd), 2048);
assert(msg_tag_get_prot(tag) >= 0);
tag = share_mem_map(shm_hd, 3, &addr, &size);
assert(msg_tag_get_prot(tag) >= 0);
ret = ns_query("/dm9000", &net_drv_hd);
assert(ret >= 0);
while (1)
{
EXTI15_10_IRQHandler();
// EXTI15_10_IRQHandler();
int ret = net_drv_cli_read(net_drv_hd, shm_hd);
if (ret > 0)
{
lwip_pkt_handle_raw((uint8_t *)addr, ret);
}
}
return 0;
}

View File

@@ -182,3 +182,7 @@ void lwip_pkt_handle(void)
{
ethernetif_input(&gnetif);
}
void lwip_pkt_handle_raw(uint8_t *data, int len)
{
ethernetif_input_raw(&gnetif, data, len);
}

View File

@@ -34,7 +34,7 @@ endif()
# -mfloat-abi=soft -u _printf_float
set(CMAKE_C_FLAGS "-mcpu=${CONFIG_ARCH} -O0 -g3 -lc -lrdimon -mfloat-abi=${FLOAT_TYPE} -u _printf_float -D=MKRTOS \
set(CMAKE_C_FLAGS "-mcpu=${CONFIG_ARCH} -O2 -g3 -lc -lrdimon -mfloat-abi=${FLOAT_TYPE} -u _printf_float -D=MKRTOS \
-std=gnu11 -ffunction-sections -fdata-sections -fno-builtin \
-nostartfiles -nodefaultlibs -nostdlib -nostdinc -Xlinker \
-fno-stack-protector -Wl,--gc-sections \