fix:删除4G模组tools目录

This commit is contained in:
2026-04-30 17:16:01 +08:00
parent 36fb7fd027
commit 0d7a8564e0
36 changed files with 703 additions and 3205 deletions

View File

@@ -1,14 +1,115 @@
-- CMD -- cmd.lua
require "linksocket" -- 功能:解析串口帧,调用 linksocket 接口,执行系统命令
require "socket"
require "sys"
function handleCmd01(subCmd, payload) local log = require "log"
--sendToSocket(subCmd, payload) --向socket发送数据 local sys = require "sys"
sendToSocket(subCmd, payload) local uart = require "uart"
log.info("CMD 0x01 received, sub:", subCmd, "data len:", #payload) local linksocket = require "linksocket"
local uartID = 1
-- 辅助函数:字节转十六进制(调试用)
local function toHexcode(str)
if not str then return "" end
local hex = ""
for i = 1, #str do
hex = hex .. string.format("%02X", str:byte(i))
end
return hex
end end
function handleCmd02(subCmd, payload) -- 发送通用响应帧55 AA 83 subCmd socketId status AA 55
local function sendResponse(subCmd, socketId, status)
local frame = string.char(0x55, 0xAA, 0x83, subCmd, socketId, status, 0xAA, 0x55)
uart.write(uartID, frame)
log.debug("Response: subCmd=", subCmd, "socketId=", socketId, "status=", status)
end
-- 命令处理函数
local function handleCmd01(subCmd, payload)
local socketId = subCmd
if socketId < 1 or socketId > 6 then
log.error("Invalid socket id in cmd 0x01:", socketId)
sendResponse(0x01, socketId, 1)
return
end
local success = linksocket.sendToSocket(socketId, payload)
if not success then
log.warn("Send failed, socket", socketId, "not connected")
sendResponse(0x01, socketId, 1)
else
log.info("Data sent to socket", socketId, "len=", #payload)
end
end
local function handleCmd02()
log.info("System restart command received")
sys.restart() sys.restart()
end end
local function handleCmd03(subCmd, payload)
if #payload < 1 then
log.error("Cmd 0x03 missing socket id")
return
end
local socketId = payload:byte(1)
if socketId < 1 or socketId > 6 then
log.error("Invalid socket id in cmd 0x03:", socketId)
sendResponse(subCmd, socketId, 1)
return
end
if subCmd == 0x01 then
local ok = linksocket.setKeepConnecting(socketId, true)
if ok then
sendResponse(subCmd, socketId, 3)
else
sendResponse(subCmd, socketId, 1)
end
elseif subCmd == 0x02 then
local ok = linksocket.setKeepConnecting(socketId, false)
if ok then
sendResponse(subCmd, socketId, 0)
else
sendResponse(subCmd, socketId, 1)
end
else
log.error("Unknown subCmd for 0x03:", subCmd)
sendResponse(subCmd, socketId, 1)
end
end
-- 对外接口:处理串口接收到的原始数据
local function process(rawData)
if not rawData or #rawData < 5 then
log.warn("Short data received, ignore")
return
end
log.info("CMD raw data:", toHexcode(rawData))
if rawData:byte(1) == 0x55 and rawData:byte(2) == 0xAA
and rawData:byte(-2) == 0xAA and rawData:byte(-1) == 0x55 then
local mainCmd = rawData:byte(3)
local subCmd = rawData:byte(4)
local payload = rawData:sub(5, -3)
if mainCmd == 0x01 then
handleCmd01(subCmd, payload)
elseif mainCmd == 0x02 then
handleCmd02()
elseif mainCmd == 0x03 then
handleCmd03(subCmd, payload)
else
log.warn("Unknown main command:", mainCmd)
end
else
log.warn("Invalid frame header/footer")
end
end
-- 模块接口
local M = {
process = process,
}
return M

View File

@@ -1,83 +1,160 @@
require "socket" -- linksocket.lua
require "log" -- 功能:管理多个 TCP Socket 连接,支持手动连接/断开,自动重连,数据收发
-- 目标服务器IP和端口 local log = require "log"
local ip, port = "121.43.69.62", "8767" local sys = require "sys"
-- 连接数量 local socket = require "socket"
local clientCount = 1
-- 存储所有客户端 -- 服务器配置
local SERVER_IP = "121.43.69.62"
local SERVER_PORT = 8767
local MAX_CLIENTS = 6
-- 客户端状态表
local clients = {} local clients = {}
local keepConnecting = {}
local recvCallback = nil
-- 初始化多个socket连接 -- 初始化所有socket槽位
for i = 1, clientCount do for i = 1, MAX_CLIENTS do
local client = { clients[i] = {
id = i, id = i,
socket = nil, socket = nil,
connected = false connected = false
} }
keepConnecting[i] = false
end
-- 为每个socket创建独立的连接任务 -- 发送连接状态响应
local function sendConnStatus(subCmd, socketId, status)
local uart = require "uart"
local frame = string.char(0x55, 0xAA, 0x83, subCmd, socketId, status, 0xAA, 0x55)
uart.write(1, frame)
log.debug("Socket", socketId, "status response, subCmd=", subCmd, "status=", status)
end
-- 设置是否保持连接
local function setKeepConnecting(id, keep)
if id < 1 or id > MAX_CLIENTS then
return false
end
keepConnecting[id] = keep
if not keep and clients[id].connected and clients[id].socket then
clients[id].socket:close()
clients[id].socket = nil
clients[id].connected = false
sendConnStatus(0x02, id, 0)
end
return true
end
-- 发送数据到指定socket
local function sendToSocket(id, data)
if id < 1 or id > MAX_CLIENTS then
log.error("sendToSocket: invalid id", id)
return false
end
if clients[id].connected and clients[id].socket then
clients[id].socket:asyncSend(data)
log.info("Send to socket", id, "len=", #data)
return true
else
log.warn("Socket", id, "not connected, cannot send")
return false
end
end
-- 注册数据接收回调
local function setRecvCallback(cb)
recvCallback = cb
end
-- 为每个socket创建常驻任务
for id = 1, MAX_CLIENTS do
sys.taskInit(function() sys.taskInit(function()
local socketId = id
log.debug("Socket", socketId, "control task started")
while true do while true do
while not socket.isReady() do sys.wait(1000) end while not keepConnecting[socketId] do
client.socket = socket.tcp() sys.wait(1000)
log.debug("Client " .. client.id .. ": Connecting to " .. ip .. ":" .. port)
while not client.socket:connect(ip, port) do
log.warn("Client " .. client.id .. ": Connection failed, retrying...")
sys.wait(2000)
end end
client.connected = true
log.debug("Client " .. client.id .. ": Connected successfully")
-- 发送连接成功信息到串口
uart.write(1, "Socket " .. client.id .. " connected\r\n")
-- 保持连接并处理数据 while keepConnecting[socketId] do
while client.socket:asyncSelect(60, "ping") do end while not socket.isReady() do
if not keepConnecting[socketId] then break end
sys.wait(1000)
end
if not keepConnecting[socketId] then break end
client.connected = false local sock = socket.tcp()
client.socket:close() log.debug("Socket", socketId, "connecting to", SERVER_IP, SERVER_PORT)
log.error("Client " .. client.id .. ": Disconnected") local connected = false
-- 发送断开连接信息到串口 while not connected and keepConnecting[socketId] do
connected = sock:connect(SERVER_IP, SERVER_PORT)
if not connected then
log.warn("Socket", socketId, "connect failed, retry in 3s")
sys.wait(3000)
end
end
if not keepConnecting[socketId] then
if sock then sock:close() end
break
end
clients[socketId].socket = sock
clients[socketId].connected = true
log.info("Socket", socketId, "connected")
sendConnStatus(0x01, socketId, 0)
while keepConnecting[socketId] and clients[socketId].connected do
local ok = sock:asyncSelect(60, "recv")
if not ok then
log.warn("Socket", socketId, "connection lost")
break
end
sys.wait(100)
end
if clients[socketId].socket then
clients[socketId].socket:close()
clients[socketId].socket = nil
end
clients[socketId].connected = false
if not keepConnecting[socketId] then
sendConnStatus(0x02, socketId, 0)
break
else
log.info("Socket", socketId, "will reconnect after 3s")
sys.wait(3000)
end
end
end end
end) end)
-- 存储客户端
clients[i] = client
end end
-- 订阅底层Socket接收事件
local function toHexcode(str) sys.subscribe("SOCKET_RECV", function(socketId)
local hexcode = ""
for i = 1, #str do
hexcode = hexcode .. string.format("%02X", str:byte(i))
end
return hexcode
end
-- 测试代码,异步回调接收数据
sys.subscribe("SOCKET_RECV", function(id)
-- 遍历所有客户端,找到对应的连接
for i, client in ipairs(clients) do for i, client in ipairs(clients) do
if client.socket and client.socket.id == id then if client.socket and client.socket.id == socketId and client.connected then
-- 转发到串口添加socket标识并清理数据
local data = client.socket:asyncRecv() local data = client.socket:asyncRecv()
log.info("Client " .. client.id .. ": Received data: " .. toHexcode(data)) if data and #data > 0 then
-- 转发到串口添加socket标识 log.info("Socket", client.id, "received data len=", #data)
local frame = string.char(0x55) .. string.char(0xAA) .. string.char(0x01) .. string.char(i) .. string.char(#data) .. data .. string.char(0xAA) .. string.char(0x55) if recvCallback then
uart.write(1, frame) recvCallback(client.id, data)
end
end
break break
end end
end end
end) end)
-- 模块接口
local M = {
-- 发送数据到指定socket setKeepConnecting = setKeepConnecting,
function sendToSocket(id_byte, msg) sendToSocket = sendToSocket,
if clients[id_byte] and clients[id_byte].socket and clients[id_byte].connected then setRecvCallback = setRecvCallback,
clients[id_byte].socket:asyncSend(msg) }
else return M
log.error("Socket " .. id_byte .. " not connected or does not exist")
end
end

View File

@@ -1,9 +1,5 @@
--- testSocket -- main.lua
-- @module asyncSocket -- 功能:初始化硬件、网络、串口,注册回调,启动系统
-- @author AIRM2M
-- @license MIT
-- @copyright openLuat.com
-- @release 2018.10.27
PROJECT = "4G_NETWORK" PROJECT = "4G_NETWORK"
VERSION = "1.0.0" VERSION = "1.0.0"
@@ -11,55 +7,42 @@ VERSION = "1.0.0"
require "sys" require "sys"
require "net" require "net"
require "log" require "log"
require "cmd"
require "uart" require "uart"
require "linksocket" require "netLed"
require "pmd"
-- 初始化 UART1 -- 初始化UART1
uart.setup(1, 115200, 8, uart.PAR_NONE, uart.STOP_1) local uartID = 1
uart.setup(uartID, 115200, 8, uart.PAR_NONE, uart.STOP_1)
-- 启动网络指示灯功能模块 -- 启动网络指示灯功能模块
require "netLed" pmd.ldoset(2, pmd.LDO_VLCD)
pmd.ldoset(2,pmd.LDO_VLCD) netLed.setup(true, pio.P0_1, pio.P0_4)
netLed.setup(true,pio.P0_1,pio.P0_4)
local uartID = 1 -- 初始化网络
net.startQueryAll(8 * 1000, 60 * 1000)
ril.request("AT+RNDISCALL=0,1")
-- 加载自定义模块(必须放在网络初始化之后)
local cmd = require "cmd"
local linksocket = require "linksocket"
local function toHexcode(str) -- 注册Socket数据接收回调
local hexcode = "" linksocket.setRecvCallback(function(socketId, data)
for i = 1, #str do -- 打包帧格式55 AA 01 id len data AA 55
hexcode = hexcode .. string.format("%02X", str:byte(i)) local frame = string.char(0x55, 0xAA, 0x01, socketId, #data) .. data .. string.char(0xAA, 0x55)
end uart.write(uartID, frame)
return hexcode log.info("Forward data from socket", socketId, "len=", #data)
end end)
-- 串口数据接收处理
uart.on(uartID, "receive", function() uart.on(uartID, "receive", function()
local data = uart.read(uartID, 300) local data = uart.read(uartID, 300)
if data and type(data) == "string" and #data > 0 then if data and #data > 0 then
log.info("UART received:", toHexcode(data)) cmd.process(data)
if data:byte(1) == 0x55 and data:byte(2) == 0xAA and data:byte(-2) == 0xAA and data:byte(-1) == 0x55 then
local Main_Cmd = data:byte(3)
local Sub_Cmd = data:byte(4)
local payload = data:sub(5, -3)
if Main_Cmd ==0x01 then
handleCmd01(Sub_Cmd, payload)
end
if Main_Cmd == 0x02 then
handleCmd02(Sub_Cmd, payload)
end
end
else
log.warn("UART receive callback triggered but no valid data")
end end
end) end)
-- 启动系统
net.startQueryAll(8 * 1000, 60 * 1000)
ril.request("AT+RNDISCALL=0,1")
sys.init(0, 0) sys.init(0, 0)
sys.run() sys.run()

File diff suppressed because one or more lines are too long

View File

@@ -1,59 +0,0 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* File Name : FMC.h
* Description : This file provides code for the configuration
* of the FMC peripheral.
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __FMC_H
#define __FMC_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
extern NAND_HandleTypeDef hnand1;
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_FMC_Init(void);
void HAL_NAND_MspInit(NAND_HandleTypeDef* hnand);
void HAL_NAND_MspDeInit(NAND_HandleTypeDef* hnand);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /*__FMC_H */
/**
* @}
*/
/**
* @}
*/

View File

@@ -47,7 +47,7 @@
/* #define HAL_DMA2D_MODULE_ENABLED */ /* #define HAL_DMA2D_MODULE_ENABLED */
#define HAL_ETH_MODULE_ENABLED #define HAL_ETH_MODULE_ENABLED
/* #define HAL_ETH_LEGACY_MODULE_ENABLED */ /* #define HAL_ETH_LEGACY_MODULE_ENABLED */
#define HAL_NAND_MODULE_ENABLED /* #define HAL_NAND_MODULE_ENABLED */
/* #define HAL_NOR_MODULE_ENABLED */ /* #define HAL_NOR_MODULE_ENABLED */
/* #define HAL_OTFDEC_MODULE_ENABLED */ /* #define HAL_OTFDEC_MODULE_ENABLED */
/* #define HAL_SRAM_MODULE_ENABLED */ /* #define HAL_SRAM_MODULE_ENABLED */

View File

@@ -1,233 +0,0 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* File Name : FMC.c
* Description : This file provides code for the configuration
* of the FMC peripheral.
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "fmc.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
NAND_HandleTypeDef hnand1;
/* FMC initialization function */
void MX_FMC_Init(void)
{
/* USER CODE BEGIN FMC_Init 0 */
/* USER CODE END FMC_Init 0 */
FMC_NAND_PCC_TimingTypeDef ComSpaceTiming = {0};
FMC_NAND_PCC_TimingTypeDef AttSpaceTiming = {0};
/* USER CODE BEGIN FMC_Init 1 */
/* USER CODE END FMC_Init 1 */
/** Perform the NAND1 memory initialization sequence
*/
hnand1.Instance = FMC_NAND_DEVICE;
/* hnand1.Init */
hnand1.Init.NandBank = FMC_NAND_BANK3;
hnand1.Init.Waitfeature = FMC_NAND_WAIT_FEATURE_ENABLE;
hnand1.Init.MemoryDataWidth = FMC_NAND_MEM_BUS_WIDTH_8;
hnand1.Init.EccComputation = FMC_NAND_ECC_DISABLE;
hnand1.Init.ECCPageSize = FMC_NAND_ECC_PAGE_SIZE_512BYTE;
hnand1.Init.TCLRSetupTime = 9;
hnand1.Init.TARSetupTime = 9;
/* hnand1.Config */
hnand1.Config.PageSize = 2048;
hnand1.Config.SpareAreaSize = 64;
hnand1.Config.BlockSize = 64;
hnand1.Config.BlockNbr = 2048;
hnand1.Config.PlaneNbr = 2;
hnand1.Config.PlaneSize = 4096;
hnand1.Config.ExtraCommandEnable = DISABLE;
/* ComSpaceTiming */
ComSpaceTiming.SetupTime = 9;
ComSpaceTiming.WaitSetupTime = 9;
ComSpaceTiming.HoldSetupTime = 10;
ComSpaceTiming.HiZSetupTime = 9;
/* AttSpaceTiming */
AttSpaceTiming.SetupTime = 9;
AttSpaceTiming.WaitSetupTime = 9;
AttSpaceTiming.HoldSetupTime = 10;
AttSpaceTiming.HiZSetupTime = 9;
if (HAL_NAND_Init(&hnand1, &ComSpaceTiming, &AttSpaceTiming) != HAL_OK)
{
Error_Handler( );
}
/* USER CODE BEGIN FMC_Init 2 */
/* USER CODE END FMC_Init 2 */
}
static uint32_t FMC_Initialized = 0;
static void HAL_FMC_MspInit(void){
/* USER CODE BEGIN FMC_MspInit 0 */
/* USER CODE END FMC_MspInit 0 */
GPIO_InitTypeDef GPIO_InitStruct = {0};
if (FMC_Initialized) {
return;
}
FMC_Initialized = 1;
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
/** Initializes the peripherals clock
*/
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_FMC;
PeriphClkInitStruct.FmcClockSelection = RCC_FMCCLKSOURCE_D1HCLK;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
Error_Handler();
}
/* Peripheral clock enable */
__HAL_RCC_FMC_CLK_ENABLE();
/** FMC GPIO Configuration
PE7 ------> FMC_D4
PE8 ------> FMC_D5
PE9 ------> FMC_D6
PE10 ------> FMC_D7
PD11 ------> FMC_CLE
PD12 ------> FMC_ALE
PD14 ------> FMC_D0
PD15 ------> FMC_D1
PC6 ------> FMC_NWAIT
PC8 ------> FMC_NCE
PD0 ------> FMC_D2
PD1 ------> FMC_D3
PD4 ------> FMC_NOE
PD5 ------> FMC_NWE
*/
/* GPIO_InitStruct */
GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
/* GPIO_InitStruct */
GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
/* GPIO_InitStruct */
GPIO_InitStruct.Pin = GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1
|GPIO_PIN_4|GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
/* GPIO_InitStruct */
GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_8;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF9_FMC;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/* USER CODE BEGIN FMC_MspInit 1 */
/* USER CODE END FMC_MspInit 1 */
}
void HAL_NAND_MspInit(NAND_HandleTypeDef* nandHandle){
/* USER CODE BEGIN NAND_MspInit 0 */
/* USER CODE END NAND_MspInit 0 */
HAL_FMC_MspInit();
/* USER CODE BEGIN NAND_MspInit 1 */
/* USER CODE END NAND_MspInit 1 */
}
static uint32_t FMC_DeInitialized = 0;
static void HAL_FMC_MspDeInit(void){
/* USER CODE BEGIN FMC_MspDeInit 0 */
/* USER CODE END FMC_MspDeInit 0 */
if (FMC_DeInitialized) {
return;
}
FMC_DeInitialized = 1;
/* Peripheral clock enable */
__HAL_RCC_FMC_CLK_DISABLE();
/** FMC GPIO Configuration
PE7 ------> FMC_D4
PE8 ------> FMC_D5
PE9 ------> FMC_D6
PE10 ------> FMC_D7
PD11 ------> FMC_CLE
PD12 ------> FMC_ALE
PD14 ------> FMC_D0
PD15 ------> FMC_D1
PC6 ------> FMC_NWAIT
PC8 ------> FMC_NCE
PD0 ------> FMC_D2
PD1 ------> FMC_D3
PD4 ------> FMC_NOE
PD5 ------> FMC_NWE
*/
HAL_GPIO_DeInit(GPIOE, GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10);
HAL_GPIO_DeInit(GPIOD, GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_14|GPIO_PIN_15
|GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5);
HAL_GPIO_DeInit(GPIOC, GPIO_PIN_6|GPIO_PIN_8);
/* USER CODE BEGIN FMC_MspDeInit 1 */
/* USER CODE END FMC_MspDeInit 1 */
}
void HAL_NAND_MspDeInit(NAND_HandleTypeDef* nandHandle){
/* USER CODE BEGIN NAND_MspDeInit 0 */
/* USER CODE END NAND_MspDeInit 0 */
HAL_FMC_MspDeInit();
/* USER CODE BEGIN NAND_MspDeInit 1 */
/* USER CODE END NAND_MspDeInit 1 */
}
/**
* @}
*/
/**
* @}
*/

View File

@@ -1,749 +0,0 @@
/**
****************************************************************************************************
* @file ftl.c
* @author 正点原子团队(ALIENTEK)
* @version V1.0
* @date 2023-03-24
* @brief NAND FLASH FTL层算法 代码
* @license Copyright (c) 2022-2032, 广州市星翼电子科技有限公司
****************************************************************************************************
* @attention
*
* 实验平台:正点原子 阿波罗 H743开发板
* 在线视频:www.yuanzige.com
* 技术论坛:www.openedv.com
* 公司网址:www.alientek.com
* 购买地址:openedv.taobao.com
*
* 修改说明
* V1.0 20230324
* 第一次发布
*
****************************************************************************************************
*/
#include "string.h"
#include "./BSP/NAND/ftl.h"
#include "./MALLOC/malloc.h"
#include "./BSP/NAND/nand.h"
#include "./SYSTEM/usart/usart.h"
/**
* 每个块,第一个page的spare区,前四个字节的含义:
* 第一个字节,表示该块是否是坏块:0XFF,正常块;其他值,坏块.
* 第二个字节,表示该块是否被用过:0XFF,没有写过数据;0XCC,写过数据了.
* 第三和第四个字节,表示该块所属的逻辑块编号.
* 每个page,spare区16字节以后的字节含义:
* 第十六字节开始,后续每4个字节用于存储一个扇区(大小:NAND_ECC_SECTOR_SIZE)的ECC值,用于ECC校验
*/
/**
* @brief FTL层初始化
* @param 无
* @retval 0,正常;其他,失败
*/
uint8_t ftl_init(void)
{
uint8_t temp;
if (nand_init())
{
return 1; /* 初始化NAND FLASH */
}
if (nand_dev.lut)
{
myfree(SRAMIN, nand_dev.lut);
}
nand_dev.lut = mymalloc(SRAMIN, (nand_dev.block_totalnum) * 2); /* 给LUT表申请内存 */
memset(nand_dev.lut, 0, nand_dev.block_totalnum * 2); /* 全部清理 */
if (!nand_dev.lut)
{
return 1; /* 内存申请失败 */
}
temp = ftl_create_lut(1);
if (temp)
{
printf("format nand flash...\r\n");
temp = ftl_format(); /* 格式化NAND */
if (temp)
{
printf("format failed!\r\n");
return 2;
}
}
else /* 创建LUT表成功 */
{
printf("total block num: %d\r\n", nand_dev.block_totalnum);
printf("good block num: %d\r\n", nand_dev.good_blocknum);
printf("valid block num: %d\r\n", nand_dev.valid_blocknum);
}
return 0;
}
/**
* @brief 标记某一个块为坏块
* @param blocknum : 块编号,范围:0~(block_totalnum-1)
* @retval 无
*/
void ftl_badblock_mark(uint32_t blocknum)
{
uint32_t temp = 0XAAAAAAAA;/* 坏块标记mark,任意值都OK,只要不是0XFF.这里写前4个字节,方便ftl_find_unused_block函数检查坏块.(不检查备份区,以提高速度) */
nand_writespare(blocknum * nand_dev.block_pagenum, 0, (uint8_t *)&temp, 4); /* 在第一个page的spare区,第一个字节做坏块标记(前4个字节都写) */
nand_writespare(blocknum * nand_dev.block_pagenum + 1, 0, (uint8_t *)&temp, 4); /* 在第二个page的spare区,第一个字节做坏块标记(备份用,前4个字节都写) */
}
/**
* @brief 检查某一块是否是坏块
* @param blocknum : 块编号,范围:0~(block_totalnum-1)
* @retval 0,好块;
* 其他,坏块
*/
uint8_t ftl_check_badblock(uint32_t blocknum)
{
uint8_t flag = 0;
nand_readspare(blocknum * nand_dev.block_pagenum, 0, &flag, 1); /* 读取坏块标志 */
if (flag == 0XFF) /* 好块?,读取备份区坏块标记 */
{
nand_readspare(blocknum * nand_dev.block_pagenum + 1, 0, &flag, 1); /* 读取备份区坏块标志 */
if (flag == 0XFF)
{
return 0; /* 好块 */
}
else return 1; /* 坏块 */
}
return 2;
}
/**
* @brief 标记某一个块已经使用
* @param blocknum : 块编号,范围:0~(block_totalnum-1)
* @retval 0,成功;
* 其他,失败
*/
uint8_t ftl_used_blockmark(uint32_t blocknum)
{
uint8_t buf[4];
uint8_t temp = 0;
nand_readspare(blocknum * nand_dev.block_pagenum, 0, buf, 4); /* 读出4字节 */
buf[1] = 0XCC;
temp = nand_writespare(blocknum * nand_dev.block_pagenum, 0, buf, 4); /* 写入块已经被使用标志 */
return temp;
}
/**
* @brief 从给定的块开始找到往前找到一个未被使用的块(指定奇数/偶数)
* @param sblock : 开始块,范围:0~(block_totalnum-1)
* @param flag : 0,偶数快; 1,奇数块.
* @retval 0XFFFFFFFF,失败;
* 其他值,未使用块号
*/
uint32_t ftl_find_unused_block(uint32_t sblock, uint8_t flag)
{
uint32_t temp = 0;
uint32_t blocknum = 0;
for (blocknum = sblock + 1; blocknum > 0; blocknum--)
{
if (((blocknum - 1) % 2) == flag) /* 奇偶合格,才检测 */
{
nand_readspare((blocknum - 1) * nand_dev.block_pagenum, 0, (uint8_t *)&temp, 4); /* 读块是否被使用标记 */
if (temp == 0XFFFFFFFF)
{
return (blocknum - 1); /* 找到一个空块,返回块编号 */
}
}
}
return 0XFFFFFFFF; /* 未找到空余块 */
}
/**
* @brief 查找与给定块在同一个plane内的未使用的块
* @param sblock : 给定块,范围:0~(block_totalnum-1)
* @retval 0XFFFFFFFF,失败;
* 其他值,未使用块号
*/
uint32_t ftl_find_same_plane_unusedBlock(uint32_t sblock)
{
static uint32_t curblock = 0XFFFFFFFF;
uint32_t unusedblock = 0;
if (curblock > (nand_dev.block_totalnum - 1))
{
curblock = nand_dev.block_totalnum - 1; /* 超出范围了,强制从最后一个块开始 */
}
unusedblock = ftl_find_unused_block(curblock, sblock % 2); /* 从当前块,开始,向前查找空余块 */
if (unusedblock == 0XFFFFFFFF && curblock < (nand_dev.block_totalnum - 1)) /* 未找到,且不是从最末尾开始找的 */
{
curblock = nand_dev.block_totalnum - 1; /* 强制从最后一个块开始 */
unusedblock = ftl_find_unused_block(curblock, sblock % 2);/* 从最末尾开始,重新找一遍 */
}
if (unusedblock == 0XFFFFFFFF)
{
return 0XFFFFFFFF; /* 找不到空闲block */
}
curblock = unusedblock; /* 当前块号等于未使用块编号.下次则从此处开始查找 */
return unusedblock; /* 返回找到的空闲block */
}
/**
* @brief 将一个块的数据拷贝到另一块,并且可以写入数据
* @param source_pagenum : 要写入数据的页地址,范围:0~(block_pagenum*block_totalnum-1)
* @param colnum : 要写入的列开始地址(也就是页内地址),范围:0~(page_totalsize-1)
* @param pbuffer : 要写入的数据
* @param numbytetowrite : 要写入的字节数,该值不能超过块内剩余容量大小
* @retval 0,成功;
* 其他,失败
*/
uint8_t ftl_copy_and_write_to_block(uint32_t source_pagenum, uint16_t colnum, uint8_t *pbuffer, uint32_t numbytetowrite)
{
uint16_t i = 0, temp = 0, wrlen;
uint32_t source_block = 0, pageoffset = 0;
uint32_t unusedblock = 0;
source_block = source_pagenum / nand_dev.block_pagenum; /* 获得页所在的块号 */
pageoffset = source_pagenum % nand_dev.block_pagenum; /* 获得页在所在块内的偏移 */
retry:
unusedblock = ftl_find_same_plane_unusedBlock(source_block); /* 查找与源块在一个plane的未使用块 */
if (unusedblock > nand_dev.block_totalnum)
{
return 1; /* 当找到的空余块号大于块总数量的话肯定是出错了 */
}
for (i = 0; i < nand_dev.block_pagenum; i++) /* 将一个块的数据复制到找到的未使用块中 */
{
if (i >= pageoffset && numbytetowrite) /* 数据要写入到当前页 */
{
if (numbytetowrite > (nand_dev.page_mainsize - colnum)) /* 要写入的数据,超过了当前页的剩余数据 */
{
wrlen = nand_dev.page_mainsize - colnum; /* 写入长度等于当前页剩余数据长度 */
}
else
{
wrlen = numbytetowrite; /* 写入全部数据 */
}
temp = nand_copypage_withwrite(source_block * nand_dev.block_pagenum + i, unusedblock * nand_dev.block_pagenum + i, colnum, pbuffer, wrlen);
colnum = 0; /* 列地址归零 */
pbuffer += wrlen; /* 写地址偏移 */
numbytetowrite -= wrlen; /* 写入数据减少 */
}
else /* 无数据写入,直接拷贝即可 */
{
temp = nand_copypage_withoutwrite(source_block * nand_dev.block_pagenum + i, unusedblock * nand_dev.block_pagenum + i);
}
if (temp) /* 返回值非零,当坏块处理 */
{
ftl_badblock_mark(unusedblock); /* 标记为坏块 */
ftl_create_lut(1); /* 重建LUT表 */
goto retry;
}
}
if (i == nand_dev.block_pagenum) /* 拷贝完成 */
{
ftl_used_blockmark(unusedblock); /* 标记块已经使用 */
nand_eraseblock(source_block); /* 擦除源块 */
//printf("\r\ncopy block %d to block %d\r\n",source_block,unusedblock);/* 打印调试信息 */
for (i = 0; i < nand_dev.block_totalnum; i++) /* 修正LUT表用unusedblock替换source_block */
{
if (nand_dev.lut[i] == source_block)
{
nand_dev.lut[i] = unusedblock;
break;
}
}
}
return 0; /* 成功 */
}
/**
* @brief 逻辑块号转换为物理块号
* @param lbnnum : 逻辑块编号
* @retval 物理块编号
*/
uint16_t ftl_lbn_to_pbn(uint32_t lbnnum)
{
uint16_t PBNNo = 0;
/* 当逻辑块号大于有效块数的时候返回0XFFFF */
if (lbnnum > nand_dev.valid_blocknum)
{
return 0XFFFF;
}
PBNNo = nand_dev.lut[lbnnum];
return PBNNo;
}
/**
* @brief 写扇区(支持多扇区写)FATFS文件系统使用
* @param pbuffer : 要写入的数据
* @param sectorno : 起始扇区号
* @param sectorsize : 扇区大小(不能大于NAND_ECC_SECTOR_SIZE定义的大小,否则会出错!!)
* @param sectorcount : 要写入的扇区数量
* @retval 0,成功;
* 其他,失败
*/
uint8_t ftl_write_sectors(uint8_t *pbuffer, uint32_t sectorno, uint16_t sectorsize, uint32_t sectorcount)
{
uint8_t flag = 0;
uint16_t temp;
uint32_t i = 0;
uint16_t wsecs; /* 写页大小 */
uint32_t wlen; /* 写入长度 */
uint32_t LBNNo; /* 逻辑块号 */
uint32_t PBNNo; /* 物理块号 */
uint32_t PhyPageNo; /* 物理页号 */
uint32_t PageOffset; /* 页内偏移地址 */
uint32_t BlockOffset; /* 块内偏移地址 */
uint32_t markdpbn = 0XFFFFFFFF; /* 标记了的物理块编号 */
for (i = 0; i < sectorcount; i++)
{
LBNNo = (sectorno + i) / (nand_dev.block_pagenum * (nand_dev.page_mainsize / sectorsize)); /* 根据逻辑扇区号和扇区大小计算出逻辑块号 */
PBNNo = ftl_lbn_to_pbn(LBNNo); /* 将逻辑块转换为物理块 */
if (PBNNo >= nand_dev.block_totalnum)
{
return 1; /* 物理块号大于NAND FLASH的总块数,则失败. */
}
BlockOffset = ((sectorno + i) % (nand_dev.block_pagenum * (nand_dev.page_mainsize / sectorsize))) * sectorsize; /* 计算块内偏移 */
PhyPageNo = PBNNo * nand_dev.block_pagenum + BlockOffset / nand_dev.page_mainsize; /* 计算出物理页号 */
PageOffset = BlockOffset % nand_dev.page_mainsize; /* 计算出页内偏移地址 */
temp = nand_dev.page_mainsize - PageOffset; /* page内剩余字节数 */
temp /= sectorsize; /* 可以连续写入的sector数 */
wsecs = sectorcount - i; /* 还剩多少个sector要写 */
if (wsecs >= temp)
{
wsecs = temp; /* 大于可连续写入的sector数,则写入temp个扇区 */
}
wlen = wsecs * sectorsize; /* 每次写wsecs个sector */
/* 读出写入大小的内容判断是否全为0XFF */
flag = nand_readpagecomp(PhyPageNo, PageOffset, 0XFFFFFFFF, wlen / 4, &temp); /* 读一个wlen/4大小个数据,并与0XFFFFFFFF对比 */
if (flag)
{
return 2; /* 读写错误,坏块 */
}
if (temp == (wlen / 4))
{
flag = nand_writepage(PhyPageNo, PageOffset, pbuffer, wlen);/* 全为0XFF,可以直接写数据 */
}
else
{
flag = 1; /* 不全是0XFF,则另作处理 */
}
if (flag == 0 && (markdpbn != PBNNo)) /* 全是0XFF,且写入成功,且标记了的物理块与当前物理块不同 */
{
flag = ftl_used_blockmark(PBNNo); /* 标记此块已经使用 */
markdpbn = PBNNo; /* 标记完成,标记块=当前块,防止重复标记 */
}
if (flag) /* 不全为0XFF/标记失败,将数据写到另一个块 */
{
temp = ((uint32_t)nand_dev.block_pagenum * nand_dev.page_mainsize - BlockOffset) / sectorsize;/* 计算整个block还剩下多少个SECTOR可以写入 */
wsecs = sectorcount - i; /* 还剩多少个sector要写 */
if (wsecs >= temp)
{
wsecs = temp; /* 大于可连续写入的sector数,则写入temp个扇区 */
}
wlen = wsecs * sectorsize; /* 每次写wsecs个sector */
flag = ftl_copy_and_write_to_block(PhyPageNo, PageOffset, pbuffer, wlen); /* 拷贝到另外一个block,并写入数据 */
if (flag)
{
return 3; /* 失败 */
}
}
i += wsecs - 1;
pbuffer += wlen; /* 数据缓冲区指针偏移 */
}
return 0;
}
/**
* @brief 读扇区(支持多扇区读)FATFS文件系统使用
* @param pbuffer : 数据缓存区
* @param sectorno : 起始扇区号
* @param sectorsize : 扇区大小
* @param sectorcount : 要写入的扇区数量
* @retval 0,成功;
* 其他,失败
*/
uint8_t ftl_read_sectors(uint8_t *pbuffer, uint32_t sectorno, uint16_t sectorsize, uint32_t sectorcount)
{
uint8_t flag = 0;
uint16_t rsecs; /* 单次读取页数 */
uint32_t i = 0;
uint32_t LBNNo; /* 逻辑块号 */
uint32_t PBNNo; /* 物理块号 */
uint32_t PhyPageNo; /* 物理页号 */
uint32_t PageOffset; /* 页内偏移地址 */
uint32_t BlockOffset; /* 块内偏移地址 */
for (i = 0; i < sectorcount; i++)
{
LBNNo = (sectorno + i) / (nand_dev.block_pagenum * (nand_dev.page_mainsize / sectorsize));/* 根据逻辑扇区号和扇区大小计算出逻辑块号 */
PBNNo = ftl_lbn_to_pbn(LBNNo); /* 将逻辑块转换为物理块 */
if (PBNNo >= nand_dev.block_totalnum)
{
return 1; /* 物理块号大于NAND FLASH的总块数,则失败. */
}
BlockOffset = ((sectorno + i) % (nand_dev.block_pagenum * (nand_dev.page_mainsize / sectorsize))) * sectorsize; /* 计算块内偏移 */
PhyPageNo = PBNNo * nand_dev.block_pagenum + BlockOffset / nand_dev.page_mainsize; /* 计算出物理页号 */
PageOffset = BlockOffset % nand_dev.page_mainsize; /* 计算出页内偏移地址 */
rsecs = (nand_dev.page_mainsize - PageOffset) / sectorsize; /* 计算一次最多可以读取多少页 */
if (rsecs > (sectorcount - i))
{
rsecs = sectorcount - i; /* 最多不能超过SectorCount-i */
}
flag = nand_readpage(PhyPageNo, PageOffset, pbuffer, rsecs * sectorsize); /* 读取数据 */
if (flag == NSTA_ECC1BITERR) /* 对于1bit ecc错误,可能为坏块 */
{
flag = nand_readpage(PhyPageNo, PageOffset, pbuffer, rsecs * sectorsize); /* 重读数据,再次确认 */
if (flag == NSTA_ECC1BITERR)
{
ftl_copy_and_write_to_block(PhyPageNo, PageOffset, pbuffer, rsecs * sectorsize); /* 搬运数据 */
flag = ftl_blockcompare(PhyPageNo / nand_dev.block_pagenum, 0XFFFFFFFF); /* 全1检查,确认是否为坏块 */
if (flag == 0)
{
flag = ftl_blockcompare(PhyPageNo / nand_dev.block_pagenum, 0X00); /* 全0检查,确认是否为坏块 */
nand_eraseblock(PhyPageNo / nand_dev.block_pagenum); /* 检测完成后,擦除这个块 */
}
if (flag) /* 全0/全1检查出错,肯定是坏块了. */
{
ftl_badblock_mark(PhyPageNo / nand_dev.block_pagenum); /* 标记为坏块 */
ftl_create_lut(1); /* 重建LUT表 */
}
flag = 0;
}
}
if (flag == NSTA_ECC2BITERR)
{
flag = 0; /* 2bit ecc错误,不处理(可能是初次写入数据导致的) */
}
if (flag)
{
return 2; /* 失败 */
}
pbuffer += sectorsize * rsecs; /* 数据缓冲区指针偏移 */
i += rsecs - 1;
}
return 0;
}
/**
* @brief 重新创建LUT表
* @param mode : 0, 仅检查第一个坏块标记
* 1, 两个坏块标记都要检查(备份区也要检查)
* @retval 0,成功;
* 其他,失败
*/
uint8_t ftl_create_lut(uint8_t mode)
{
uint32_t i;
uint8_t buf[4];
uint32_t LBNnum = 0; /* 逻辑块号 */
for (i = 0; i < nand_dev.block_totalnum; i++) /* 复位LUT表初始化为无效值也就是0XFFFF */
{
nand_dev.lut[i] = 0XFFFF;
}
nand_dev.good_blocknum = 0;
for (i = 0; i < nand_dev.block_totalnum; i++)
{
nand_readspare(i * nand_dev.block_pagenum, 0, buf, 4); /* 读取4个字节 */
if (buf[0] == 0XFF && mode)
{
nand_readspare(i * nand_dev.block_pagenum + 1, 0, buf, 1); /* 好块,且需要检查2次坏块标记 */
}
if (buf[0] == 0XFF) /* 是好块 */
{
LBNnum = ((uint16_t)buf[3] << 8) + buf[2]; /* 得到逻辑块编号 */
if (LBNnum < nand_dev.block_totalnum) /* 逻辑块号肯定小于总的块数量 */
{
nand_dev.lut[LBNnum] = i; /* 更新LUT表写LBNnum对应的物理块编号 */
}
nand_dev.good_blocknum++;
}
else
{
printf("bad block index:%d\r\n", i);
}
}
/* LUT表建立完成以后检查有效块个数 */
for (i = 0; i < nand_dev.block_totalnum; i++)
{
if (nand_dev.lut[i] >= nand_dev.block_totalnum)
{
nand_dev.valid_blocknum = i;
break;
}
}
if (nand_dev.valid_blocknum < 100)
{
return 2; /* 有效块数小于100,有问题.需要重新格式化 */
}
return 0; /* LUT表创建完成 */
}
/**
* @brief FTL整个Block与某个数据对比
* @param blockx : block编号
* @param cmpval : 要与之对比的值
* @retval 0,检查成功,全部相等;
1,检查失败,有不相等的情况
*/
uint8_t ftl_blockcompare(uint32_t blockx, uint32_t cmpval)
{
uint8_t res;
uint16_t i, j, k;
for (i = 0; i < 3; i++) /* 允许3次机会 */
{
for (j = 0; j < nand_dev.block_pagenum; j++)
{
nand_readpagecomp(blockx * nand_dev.block_pagenum, 0, cmpval, nand_dev.page_mainsize / 4, &k);/* 检查一个page,并与0XFFFFFFFF对比 */
if (k != (nand_dev.page_mainsize / 4))break;
}
if (j == nand_dev.block_pagenum)
{
return 0; /* 检查合格,直接退出 */
}
res = nand_eraseblock(blockx);
if (res)
{
printf("error erase block:%d\r\n", i);
}
else
{
if (cmpval != 0XFFFFFFFF) /* 不是判断全1,则需要重写数据 */
{
for (k = 0; k < nand_dev.block_pagenum; k++)
{
nand_write_pageconst(blockx * nand_dev.block_pagenum + k, 0, 0, nand_dev.page_mainsize / 4);/* 写PAGE */
}
}
}
}
printf("bad block checked:%d\r\n", blockx);
return 1;
}
/**
* @brief FTL初始化时搜寻所有坏块,使用:擦-写-读 方式
* @note 512M的NAND ,需要约3分钟时间,来完成检测
* 对于RGB屏,由于频繁读写NAND,会引起屏幕乱闪
* @param 无
* @retval 好块的数量
*/
uint32_t ftl_search_badblock(void)
{
uint8_t *blktbl;
uint8_t res;
uint32_t i, j;
uint32_t goodblock = 0;
blktbl = mymalloc(SRAMIN, nand_dev.block_totalnum); /* 申请block坏块表内存,对应项:0,好块;1,坏块; */
nand_erasechip(); /* 全片擦除 */
for (i = 0; i < nand_dev.block_totalnum; i++) /* 第一阶段检查,检查全1 */
{
res = ftl_blockcompare(i, 0XFFFFFFFF); /* 全1检查 */
if (res)
{
blktbl[i] = 1; /* 坏块 */
}
else
{
blktbl[i] = 0;/* 好块 */
for (j = 0; j < nand_dev.block_pagenum; j++)/* 写block为全0,为后面的检查准备 */
{
nand_write_pageconst(i * nand_dev.block_pagenum + j, 0, 0, nand_dev.page_mainsize / 4);
}
}
}
for (i = 0; i < nand_dev.block_totalnum; i++) /* 第二阶段检查,检查全0 */
{
if (blktbl[i] == 0) /* 在第一阶段,没有被标记坏块的,才可能是好块 */
{
res = ftl_blockcompare(i, 0); /* 全0检查 */
if (res)
{
blktbl[i] = 1; /* 标记坏块 */
}
else
{
goodblock++;
}
}
}
nand_erasechip(); /* 全片擦除 */
for (i = 0; i < nand_dev.block_totalnum; i++) /* 第三阶段检查,标记坏块 */
{
if (blktbl[i])
{
ftl_badblock_mark(i); /* 是坏块 */
}
}
return goodblock; /* 返回好块的数量 */
}
/**
* @brief 格式化NAND 重建LUT表
* @param 无
* @retval 0,成功;
其他,失败
*/
uint8_t ftl_format(void)
{
uint8_t temp;
uint8_t buf[6];
uint32_t i, n;
uint32_t goodblock = 0;
nand_dev.good_blocknum = 0;
#if FTL_USE_BAD_BLOCK_SEARCH == 1 /* 使用擦-写-读的方式,检测坏块 */
nand_dev.good_blocknum = FTL_SearchBadBlock(); /* 搜寻坏块.耗时很久 */
#else /* 直接使用NAND FLASH的出厂坏块标志(其他块,默认是好块) */
for (i = 0; i < nand_dev.block_totalnum; i++)
{
temp = ftl_check_badblock(i); /* 检查一个块是否为坏块 */
if (temp == 0) /* 好块 */
{
temp = nand_eraseblock(i);
if (temp) /* 擦除失败,认为坏块 */
{
printf("Bad block:%d\r\n", i);
ftl_badblock_mark(i); /* 标记是坏块 */
}
else
{
nand_dev.good_blocknum++; /* 好块数量加一 */
}
}
}
#endif
printf("good_blocknum:%d\r\n", nand_dev.good_blocknum);
if (nand_dev.good_blocknum < 100)
{
return 1; /*如果好块的数量少于100则NAND Flash报废 */
}
goodblock = (nand_dev.good_blocknum * 93) / 100;/* %93的好块用于存储数据 */
n = 0;
for (i = 0; i < nand_dev.block_totalnum; i++) /* 在好块中标记上逻辑块信息 */
{
temp = ftl_check_badblock(i); /* 检查一个块是否为坏块 */
if (temp == 0) /* 好块 */
{
nand_readspare(i * nand_dev.block_pagenum, 0, buf, 4); /* 读取spare区前四个字节 */
buf[2] = (uint8_t)n;
buf[3] = (uint8_t)(n >> 8);
nand_writespare(i * nand_dev.block_pagenum, 0, buf, 4); /* 写入逻辑块编号 */
n++; /* 逻辑块编号加1 */
if (n == goodblock) break; /* 全部标记完了 */
}
}
if (ftl_create_lut(1))
{
return 2; /* 重建LUT表失败 */
}
return 0;
}

View File

@@ -1,53 +0,0 @@
/**
****************************************************************************************************
* @file ftl.h
* @author 正点原子团队(ALIENTEK)
* @version V1.0
* @date 2022-09-06
* @brief NAND FLASH FTL层算法代码
* @license Copyright (c) 2020-2032, 广州市星翼电子科技有限公司
****************************************************************************************************
* @attention
*
* 实验平台:正点原子 阿波罗 H743开发板
* 在线视频:www.yuanzige.com
* 技术论坛:www.openedv.com
* 公司网址:www.alientek.com
* 购买地址:openedv.taobao.com
*
* 修改说明
* V1.0 20220906
* 第一次发布
*
****************************************************************************************************
*/
#ifndef __FTL_H
#define __FTL_H
#include "./SYSTEM/sys/sys.h"
/* 坏块搜索控制 */
/* 如果设置为1,将在ftl_format的时候,搜寻坏块,耗时久(512M,3分钟以上),且会导致RGB屏乱闪 */
#define FTL_USE_BAD_BLOCK_SEARCH 0 /* 定义是否使用坏块搜索 */
/******************************************************************************************/
uint8_t ftl_init(void);
void ftl_badblock_mark(uint32_t blocknum);
uint8_t ftl_check_badblock(uint32_t blocknum);
uint8_t ftl_used_blockmark(uint32_t blocknum);
uint32_t ftl_find_unused_block(uint32_t sblock, uint8_t flag);
uint32_t ftl_find_same_plane_unused_block(uint32_t sblock);
uint8_t ftl_copy_and_write_to_block(uint32_t source_pagenum, uint16_t colnum, uint8_t *pbuffer, uint32_t numbyte_to_write);
uint16_t ftl_lbn_to_pbn(uint32_t lbnnum);
uint8_t ftl_write_sectors(uint8_t *pbuffer, uint32_t sectorno, uint16_t sectorsize, uint32_t sectorcount);
uint8_t ftl_read_sectors(uint8_t *pbuffer, uint32_t sectorno, uint16_t sectorsize, uint32_t sectorcount);
uint8_t ftl_create_lut(uint8_t mode);
uint8_t ftl_blockcompare(uint32_t blockx, uint32_t cmpval);
uint32_t ftl_search_badblock(void);
uint8_t ftl_format(void);
#endif

View File

@@ -49,9 +49,7 @@ void MX_GPIO_Init(void)
__HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE(); __HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOG_CLK_ENABLE(); __HAL_RCC_GPIOG_CLK_ENABLE();
/*Configure GPIO pin Output Level */ /*Configure GPIO pin Output Level */

View File

@@ -24,7 +24,6 @@
#include "memorymap.h" #include "memorymap.h"
#include "usart.h" #include "usart.h"
#include "gpio.h" #include "gpio.h"
#include "fmc.h"
/* Private includes ----------------------------------------------------------*/ /* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */ /* USER CODE BEGIN Includes */
@@ -35,15 +34,6 @@
/* Private typedef -----------------------------------------------------------*/ /* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */ /* USER CODE BEGIN PTD */
extern NAND_HandleTypeDef hnand1;
#define NAND_PAGE_SIZE 2048 // ??????(??)
#define NAND_OOB_SIZE 64 // OOB ??(??)
#define NAND_BLOCK_SIZE 64 // ?? 64 ?(???)
// ????????(????,???? SRAM3 ? DTCM)
__attribute__((aligned(4))) uint8_t nand_write_buffer[NAND_PAGE_SIZE];
__attribute__((aligned(4))) uint8_t nand_read_buffer[NAND_PAGE_SIZE + NAND_OOB_SIZE];
/* USER CODE END PTD */ /* USER CODE END PTD */
@@ -75,6 +65,7 @@ void MX_FREERTOS_Init(void);
/* Private user code ---------------------------------------------------------*/ /* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */ /* USER CODE BEGIN 0 */
/* USER CODE END 0 */ /* USER CODE END 0 */
/** /**
@@ -128,6 +119,13 @@ int main(void)
g_Init(); g_Init();
Os_Init(); Os_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */ /* USER CODE END 2 */
/* Call init function for freertos objects (in cmsis_os2.c) */ /* Call init function for freertos objects (in cmsis_os2.c) */

View File

@@ -1,962 +0,0 @@
/**
****************************************************************************************************
* @file nand.c
* @author 正点原子团队(ALIENTEK)
* @version V1.0
* @date 2022-09-06
* @brief NAND FLASH 驱动代码
* @license Copyright (c) 2020-2032, 广州市星翼电子科技有限公司
****************************************************************************************************
* @attention
*
* 实验平台:正点原子 阿波罗 H743开发板
* 在线视频:www.yuanzige.com
* 技术论坛:www.openedv.com
* 公司网址:www.alientek.com
* 购买地址:openedv.taobao.com
*
* 修改说明
* V1.0 20220906
* 第一次发布
*
****************************************************************************************************
*/
#include <stdio.h>
#include "nand.h"
NAND_HandleTypeDef g_nand_handle; /* NAND FLASH句柄 */
nand_attriute nand_dev; /* nand重要参数结构体 */
/**
* @brief 初始化NAND FLASH
* @param 无
* @retval 无
*/
uint8_t nand_init(void)
{
FMC_NAND_PCC_TimingTypeDef comspacetiming, attspacetiming;
g_nand_handle.Instance = FMC_NAND_DEVICE;
g_nand_handle.Init.NandBank = FMC_NAND_BANK3; /* NAND挂在BANK3上 */
g_nand_handle.Init.Waitfeature = FMC_NAND_PCC_WAIT_FEATURE_DISABLE; /* 关闭等待特性 */
g_nand_handle.Init.MemoryDataWidth = FMC_NAND_PCC_MEM_BUS_WIDTH_8; /* 8位数据宽度 */
g_nand_handle.Init.EccComputation = FMC_NAND_ECC_DISABLE; /* 不使用ECC */
g_nand_handle.Init.ECCPageSize = FMC_NAND_ECC_PAGE_SIZE_512BYTE; /* ECC页大小为512字节 */
g_nand_handle.Init.TCLRSetupTime = 8; /* 设置TCLR(tCLR=CLE到RE的延时)=(TCLR+SET+2)*THCLK,THCLK=1/220M=4.5ns */
g_nand_handle.Init.TARSetupTime = 8; /* 设置TAR(tAR=ALE到RE的延时)=(TAR+SET+1)*THCLK,THCLK=1/220M=4.5ns */
comspacetiming.SetupTime = 4; /* 建立时间 */
comspacetiming.WaitSetupTime = 6; /* 等待时间 */
comspacetiming.HoldSetupTime = 2; /* 保持时间 */
comspacetiming.HiZSetupTime = 3; /* 高阻态时间 */
attspacetiming.SetupTime = 4; /* 建立时间 */
attspacetiming.WaitSetupTime = 6; /* 等待时间 */
attspacetiming.HoldSetupTime = 2; /* 保持时间 */
attspacetiming.HiZSetupTime = 3; /* 高阻态时间 */
HAL_NAND_Init(&g_nand_handle, &comspacetiming, &attspacetiming);
nand_reset(); /* 复位NAND */
delay_ms(100);
nand_dev.id = nand_readid(); /* 读取ID */
nand_modeset(4); /* 设置为MODE4,高速模式 */
if (nand_dev.id == MT29F16G08ABABA) /* NAND为MT29F16G08ABABA */
{
nand_dev.page_totalsize = 4320; /* nand一个page的总大小包括spare区 */
nand_dev.page_mainsize = 4096; /* nand一个page的有效数据区大小 */
nand_dev.page_sparesize = 224; /* nand一个page的spare区大小 */
nand_dev.block_pagenum = 128; /* nand一个block所包含的page数目 */
nand_dev.plane_blocknum = 2048; /* nand一个plane所包含的block数目 */
nand_dev.block_totalnum = 4096; /* nand的总block数目 */
}
else if (nand_dev.id == MT29F4G08ABADA) /* NAND为MT29F4G08ABADA */
{
nand_dev.page_totalsize = 2112; /* nand一个page的总大小包括spare区 */
nand_dev.page_mainsize = 2048; /* nand一个page的有效数据区大小 */
nand_dev.page_sparesize = 64; /* nand一个page的spare区大小 */
nand_dev.block_pagenum = 64; /* nand一个block所包含的page数目 */
nand_dev.plane_blocknum = 2048; /* nand一个plane所包含的block数目 */
nand_dev.block_totalnum = 4096; /* nand的总block数目 */
}
else if (nand_dev.id == FSNS8B004G) /* NAND为HSENSD04ATIG */
{
nand_dev.page_totalsize = 4160; /* nand一个page的总大小包括spare区 */
nand_dev.page_mainsize = 4096; /* nand一个page的有效数据区大小 */
nand_dev.page_sparesize = 64; /* nand一个page的spare区大小 */
nand_dev.block_pagenum = 64; /* nand一个block所包含的page数目 */
nand_dev.plane_blocknum = 1024; /* nand一个plane所包含的block数目 */
nand_dev.block_totalnum = 2048; /* nand的总block数目 */
}
else return 1; /* 错误,返回 */
return 0;
}
/**
* @brief NAND FALSH底层驱动,引脚配置,时钟使能
* @note 此函数会被HAL_nand_init()调用
* @param 无
* @retval 无
*/
void HAL_NAND_MspInit(NAND_HandleTypeDef *hnand)
{
GPIO_InitTypeDef gpio_init_struct;
__HAL_RCC_FMC_CLK_ENABLE(); /* 使能FMC时钟 */
__HAL_RCC_GPIOC_CLK_ENABLE(); /* 使能GPIOC时钟 */
__HAL_RCC_GPIOD_CLK_ENABLE(); /* 使能GPIOD时钟 */
__HAL_RCC_GPIOE_CLK_ENABLE(); /* 使能GPIOE时钟 */
__HAL_RCC_GPIOG_CLK_ENABLE(); /* 使能GPIOG时钟 */
gpio_init_struct.Pin = GPIO_PIN_6;
gpio_init_struct.Mode = GPIO_MODE_INPUT; /* 输入 */
gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
gpio_init_struct.Speed = GPIO_SPEED_HIGH; /* 高速 */
HAL_GPIO_Init(GPIOC, &gpio_init_struct);
gpio_init_struct.Pin = GPIO_PIN_8;
gpio_init_struct.Mode = GPIO_MODE_AF_PP; /* 输入 */
gpio_init_struct.Pull = GPIO_NOPULL; /* 上拉 */
gpio_init_struct.Speed = GPIO_SPEED_HIGH; /* 高速 */
gpio_init_struct.Alternate = GPIO_AF9_FMC; /* 复用为FMC */
HAL_GPIO_Init(GPIOC, &gpio_init_struct);
gpio_init_struct.Alternate = GPIO_AF12_FMC; /* 复用为FMC */
/* 初始化PD0,1,4,5,11,12,14,15 */
gpio_init_struct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5 | \
GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_14 | GPIO_PIN_15;
gpio_init_struct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOD, &gpio_init_struct);
/* 初始化PE7,8,9,10*/
gpio_init_struct.Pin = GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10;
HAL_GPIO_Init(GPIOE, &gpio_init_struct);
}
/**
* @brief 设置NAND速度模式
* @param mode : 0~5, 表示速度模式
* @retval 0,成功; 其他,失败
*/
uint8_t nand_modeset(uint8_t mode)
{
*(__IO uint8_t *)(NAND_ADDRESS | NAND_CMD) = NAND_FEATURE; /* 发送设置特性命令 */
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = 0X01; /* 地址为0X01,设置mode */
*(__IO uint8_t *)NAND_ADDRESS = mode; /* P1参数,设置mode */
*(__IO uint8_t *)NAND_ADDRESS = 0;
*(__IO uint8_t *)NAND_ADDRESS = 0;
*(__IO uint8_t *)NAND_ADDRESS = 0;
if (nand_wait_for_ready() == NSTA_READY)
{
return 0; /* 成功 */
}
else return 1; /* 失败 */
}
/**
* @brief 读取NAND FLASH的ID
* @note 不同的NAND略有不同请根据自己所使用的NAND FALSH数据手册来编写函数
* @param 无
* @retval NAND FLASH的ID值
*/
uint32_t nand_readid(void)
{
uint8_t deviceid[5];
uint32_t id;
*(__IO uint8_t *)(NAND_ADDRESS | NAND_CMD) = nand_readID; /* 发送读取ID命令 */
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = 0X00;
/* ID一共有5个字节 */
deviceid[0] = *(__IO uint8_t *)NAND_ADDRESS;
deviceid[1] = *(__IO uint8_t *)NAND_ADDRESS;
deviceid[2] = *(__IO uint8_t *)NAND_ADDRESS;
deviceid[3] = *(__IO uint8_t *)NAND_ADDRESS;
deviceid[4] = *(__IO uint8_t *)NAND_ADDRESS;
/* 镁光的NAND FLASH的ID一共5个字节但是为了方便我们只取4个字节组成一个32位的ID值
根据NAND FLASH的数据手册只要是镁光的NAND FLASH那么一个字节ID的第一个字节都是0X2C
所以我们就可以抛弃这个0X2C只取后面四字节的ID值。*/
id = ((uint32_t)deviceid[1]) << 24 | ((uint32_t)deviceid[2]) << 16 | ((uint32_t)deviceid[3]) << 8 | deviceid[4];
return id;
}
/**
* @brief 读NAND状态
* @param 无
* @retval NAND状态值
* bit0:0,成功; 1,错误(编程/擦除/READ)
* bit6:0,Busy; 1,Ready
*/
uint8_t nand_readstatus(void)
{
__IO uint8_t data = 0;
*(__IO uint8_t *)(NAND_ADDRESS | NAND_CMD) = NAND_READSTA; /* 发送读状态命令 */
nand_delay(NAND_TWHR_DELAY); /* 等待tWHR,再读取状态寄存器 */
data = *(__IO uint8_t *)NAND_ADDRESS; /* 读取状态值 */
return data;
}
/**
* @brief 等待NAND准备好
* @param 无
* @retval NSTA_TIMEOUT 等待超时了
* NSTA_READY 已经准备好
*/
uint8_t nand_wait_for_ready(void)
{
uint8_t status = 0;
__IO uint32_t time = 0;
while (1) /* 等待ready */
{
status = nand_readstatus(); /* 获取状态值 */
if (status & NSTA_READY)break;
time++;
if (time >= 0X1FFFFFFF)
{
return NSTA_TIMEOUT; /* 超时 */
}
}
return NSTA_READY; /* 准备好 */
}
/**
* @brief 复位NAND
* @param 无
* @retval 0,成功; 其他,失败
*/
uint8_t nand_reset(void)
{
*(__IO uint8_t *)(NAND_ADDRESS | NAND_CMD) = NAND_RESET; /* 复位NAND */
if (nand_wait_for_ready() == NSTA_READY)
{
return 0; /* 复位成功 */
}
else return 1; /* 复位失败 */
}
/**
* @brief 等待RB信号为某个电平
* @param rb : 0,等待RB==0;
* 1,等待RB==1;
* @retval 0,成功; 1,超时
*/
uint8_t nand_waitrb(__IO uint8_t rb)
{
__IO uint32_t time = 0;
__IO uint8_t cnt = 0;
while (time < 0X1FFFFFF)
{
time++;
if (NAND_RB == rb)
{
cnt++;
}
else
{
cnt = 0;
}
if (cnt > 2)
{
return 0; /* 连续三次读取都是正确的有效电平,则认为此次数据有效!(否则-O2优化出问题!) */
}
}
return 1;
}
/**
* @brief NAND延时
* @note 一个i++至少需要4ns
* @param i : 等待的时间
* @retval 无
*/
void nand_delay(__IO uint32_t i)
{
while (i > 0)
{
i--;
}
}
/**
* @brief 读取NAND Flash的指定页指定列的数据(main区和spare区都可以使用此函数)
* @param pagenum : 要读取的页地址,范围:0~(block_pagenum*block_totalnum-1)
* @param colnum : 要读取的列开始地址(也就是页内地址),范围:0~(page_totalsize-1)
* @param *pbuffer : 指向数据存储区
* @param numbytetoread : 读取字节数(不能跨页读)
* @retval 0,成功; 其他,错误代码
*/
uint8_t nand_readpage(uint32_t pagenum, uint16_t colnum, uint8_t *pbuffer, uint16_t numbytetoread)
{
__IO uint16_t i = 0;
uint8_t res = 0;
uint8_t eccnum = 0; /* 需要计算的ECC个数每NAND_ECC_SECTOR_SIZE字节计算一个ecc */
uint8_t eccstart = 0; /* 第一个ECC值所属的地址范围 */
uint8_t errsta = 0;
uint8_t *p;
*(__IO uint8_t *)(NAND_ADDRESS | NAND_CMD) = NAND_AREA_A;
/* 发送地址 */
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)colnum;
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)(colnum >> 8);
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)pagenum;
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)(pagenum >> 8);
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)(pagenum >> 16);
*(__IO uint8_t *)(NAND_ADDRESS | NAND_CMD) = NAND_AREA_TRUE1;
/**
* 下面两行代码是等待R/B引脚变为低电平其实主要起延时作用的等待NAND操作R/B引脚。因为我们是通过
* 将STM32的NWAIT引脚(NAND的R/B引脚)配置为普通IO代码中通过读取NWAIT引脚的电平来判断NAND是否准备
* 就绪的。这个也就是模拟的方法所以在速度很快的时候有可能NAND还没来得及操作R/B引脚来表示NAND的忙
* 闲状态结果我们就读取了R/B引脚,这个时候肯定会出错的,事实上确实是会出错!大家也可以将下面两行
* 代码换成延时函数,只不过这里我们为了效率所以没有用延时函数。
*/
res = nand_waitrb(0); /* 等待RB=0 */
if (res)
{
return NSTA_TIMEOUT; /* 超时退出 */
}
/* 下面2行代码是真正判断NAND是否准备好的 */
res = nand_waitrb(1); /* 等待RB=1 */
if (res)
{
return NSTA_TIMEOUT; /* 超时退出 */
}
if (numbytetoread % NAND_ECC_SECTOR_SIZE) /* 不是NAND_ECC_SECTOR_SIZE的整数倍不进行ECC校验 */
{
/* 读取NAND FLASH中的值 */
for (i = 0; i < numbytetoread; i++)
{
*(__IO uint8_t *)pbuffer++ = *(__IO uint8_t *)NAND_ADDRESS;
}
}
else
{
eccnum = numbytetoread / NAND_ECC_SECTOR_SIZE; /* 得到ecc计算次数 */
eccstart = colnum / NAND_ECC_SECTOR_SIZE;
p = pbuffer;
for (res = 0; res < eccnum; res++)
{
FMC_Bank3_R->PCR |= 1 << 6; /* 使能ECC校验 */
for (i = 0; i < NAND_ECC_SECTOR_SIZE; i++) /* 读取NAND_ECC_SECTOR_SIZE个数据 */
{
*(__IO uint8_t *)pbuffer++ = *(__IO uint8_t *)NAND_ADDRESS;
}
while (!(FMC_Bank3_R -> SR & (1 << 6))); /* 等待FIFO空 */
SCB_CleanInvalidateDCache(); /* 清除无效的D-Cache */
nand_dev.ecc_hdbuf[res + eccstart] = FMC_Bank3_R -> ECCR; /* 读取硬件计算后的ECC值 */
FMC_Bank3_R -> PCR &= ~(1 << 6); /* 禁止ECC校验 */
}
i = nand_dev.page_mainsize + 0X10 + eccstart * 4; /* 从spare区的0X10位置开始读取之前存储的ecc值 */
nand_delay(NAND_TRHW_DELAY); /* 等待tRHW */
*(__IO uint8_t *)(NAND_ADDRESS | NAND_CMD) = 0X05; /* 随机读指令 */
/* 发送地址 */
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)i;
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)(i >> 8);
*(__IO uint8_t *)(NAND_ADDRESS | NAND_CMD) = 0XE0; /* 开始读数据 */
nand_delay(NAND_TWHR_DELAY); /* 等待tWHR */
pbuffer = (uint8_t *)&nand_dev.ecc_rdbuf[eccstart];
for (i = 0; i < 4 * eccnum; i++) /* 读取保存的ECC值 */
{
*(__IO uint8_t *)pbuffer++ = *(__IO uint8_t *)NAND_ADDRESS;
}
for (i = 0; i < eccnum; i++) /* 检验ECC */
{
if (nand_dev.ecc_rdbuf[i + eccstart] != nand_dev.ecc_hdbuf[i + eccstart]) /* 不相等,需要校正 */
{
printf("err hd,rd:0x%x,0x%x\r\n", nand_dev.ecc_hdbuf[i + eccstart], nand_dev.ecc_rdbuf[i + eccstart]);
printf("eccnum,eccstart:%d,%d\r\n", eccnum, eccstart);
printf("PageNum,ColNum:%d,%d\r\n", pagenum, colnum);
res = nand_ecc_correction(p + NAND_ECC_SECTOR_SIZE * i, nand_dev.ecc_rdbuf[i + eccstart], nand_dev.ecc_hdbuf[i + eccstart]);/* ECC校验 */
if (res)
{
errsta = NSTA_ECC2BITERR; /* 标记2BIT及以上ECC错误 */
}
else
{
errsta = NSTA_ECC1BITERR; /* 标记1BIT ECC错误 */
}
}
}
}
if (nand_wait_for_ready() != NSTA_READY)
{
errsta = NSTA_ERROR; /* 失败 */
}
return errsta; /* 成功 */
}
/**
* @brief 读取NAND Flash的指定页指定列的数据(main区和spare区都可以使用此函数),并对比(FTL管理时需要)
* @param pagenum : 要读取的页地址,范围:0~(block_pagenum*block_totalnum-1)
* @param colnum : 要读取的列开始地址(也就是页内地址),范围:0~(page_totalsize-1)
* @param cmpval : 要对比的值,以uint32_t为单位
* @param numbytetoread : 读取字数(以4字节为单位,不能跨页读)
* @param numbyteequal : 从初始位置持续与CmpVal值相同的数据个数
* @retval 0,成功; 其他,错误代码
*/
uint8_t nand_readpagecomp(uint32_t pagenum, uint16_t colnum, uint32_t cmpval, uint16_t numbytetoread, uint16_t *numbyteequal)
{
uint16_t i = 0;
uint8_t res = 0;
*(__IO uint8_t *)(NAND_ADDRESS | NAND_CMD) = NAND_AREA_A;
/* 发送地址 */
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)colnum;
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)(colnum >> 8);
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)pagenum;
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)(pagenum >> 8);
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)(pagenum >> 16);
*(__IO uint8_t *)(NAND_ADDRESS | NAND_CMD) = NAND_AREA_TRUE1;
/**
* 下面两行代码是等待R/B引脚变为低电平其实主要起延时作用的等待NAND操作R/B引脚。因为我们是通过
* 将STM32的NWAIT引脚(NAND的R/B引脚)配置为普通IO代码中通过读取NWAIT引脚的电平来判断NAND是否准备
* 就绪的。这个也就是模拟的方法所以在速度很快的时候有可能NAND还没来得及操作R/B引脚来表示NAND的忙
* 闲状态结果我们就读取了R/B引脚,这个时候肯定会出错的,事实上确实是会出错!大家也可以将下面两行
* 代码换成延时函数,只不过这里我们为了效率所以没有用延时函数。
*/
res = nand_waitrb(0); /* 等待RB=0 */
if (res)
{
return NSTA_TIMEOUT; /* 超时退出 */
}
/* 下面2行代码是真正判断NAND是否准备好的 */
res = nand_waitrb(1); /* 等待RB=1 */
if (res)
{
return NSTA_TIMEOUT; /* 超时退出 */
}
for (i = 0; i < numbytetoread; i++) /* 读取数据,每次读4字节 */
{
if (*(__IO uint32_t *)NAND_ADDRESS != cmpval)break; /* 如果有任何一个值,与CmpVal不相等,则退出. */
}
*numbyteequal = i; /* 与CmpVal值相同的个数 */
if (nand_wait_for_ready() != NSTA_READY)
{
return NSTA_ERROR; /* 失败 */
}
return 0; /* 成功 */
}
/**
* @brief 在NAND一页中写入指定个字节的数据(main区和spare区都可以使用此函数)
* @param pagenum : 要写入的页地址,范围:0~(block_pagenum*block_totalnum-1)
* @param colnum : 要写入的列开始地址(也就是页内地址),范围:0~(page_totalsize-1)
* @param pbuffer : 指向数据存储区
* @param numbytetowrite : 要写入的字节数,该值不能超过该页剩余字节数!!!
* @retval 0,成功; 其他,错误代码
*/
uint8_t nand_writepage(uint32_t pagenum, uint16_t colnum, uint8_t *pbuffer, uint16_t numbytetowrite)
{
__IO uint16_t i = 0;
uint8_t res = 0;
uint8_t eccnum = 0; /* 需要计算的ECC个数每NAND_ECC_SECTOR_SIZE字节计算一个ecc */
uint8_t eccstart = 0; /* 第一个ECC值所属的地址范围 */
*(__IO uint8_t *)(NAND_ADDRESS | NAND_CMD) = NAND_WRITE0;
/* 发送地址 */
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)colnum;
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)(colnum >> 8);
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)pagenum;
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)(pagenum >> 8);
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)(pagenum >> 16);
nand_delay(NAND_TADL_DELAY); /* 等待tADL */
if (numbytetowrite % NAND_ECC_SECTOR_SIZE) /* 不是NAND_ECC_SECTOR_SIZE的整数倍不进行ECC校验 */
{
for (i = 0; i < numbytetowrite; i++) /* 写入数据 */
{
*(__IO uint8_t *)NAND_ADDRESS = *(__IO uint8_t *)pbuffer++;
}
}
else
{
eccnum = numbytetowrite / NAND_ECC_SECTOR_SIZE; /* 得到ecc计算次数 */
eccstart = colnum / NAND_ECC_SECTOR_SIZE;
for (res = 0; res < eccnum; res++)
{
FMC_Bank3_R -> PCR |= 1 << 6; /* 使能ECC校验 */
for (i = 0; i < NAND_ECC_SECTOR_SIZE; i++) /* 写入NAND_ECC_SECTOR_SIZE个数据 */
{
*(__IO uint8_t *)NAND_ADDRESS = *(__IO uint8_t *)pbuffer++;
}
while (!(FMC_Bank3_R -> SR & (1 << 6))); /* 等待FIFO空 */
SCB_CleanInvalidateDCache(); /* 清除无效的D-Cache */
nand_dev.ecc_hdbuf[res + eccstart] = FMC_Bank3_R -> ECCR; /* 读取硬件计算后的ECC值 */
FMC_Bank3_R -> PCR &= ~(1 << 6); /* 禁止ECC校验 */
}
i = nand_dev.page_mainsize + 0X10 + eccstart * 4; /*计算写入ECC的spare区地址 */
nand_delay(NAND_TADL_DELAY); /* 等待tADL */
*(__IO uint8_t *)(NAND_ADDRESS | NAND_CMD) = 0X85; /* 随机写指令 */
/* 发送地址 */
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)i;
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)(i >> 8);
nand_delay(NAND_TADL_DELAY); /* 等待tADL */
pbuffer = (uint8_t *)&nand_dev.ecc_hdbuf[eccstart];
for (i = 0; i < eccnum; i++) /* 写入ECC */
{
for (res = 0; res < 4; res++)
{
*(__IO uint8_t *)NAND_ADDRESS = *(__IO uint8_t *)pbuffer++;
}
}
}
*(__IO uint8_t *)(NAND_ADDRESS | NAND_CMD) = NAND_WRITE_TURE1;
delay_us(NAND_TPROG_DELAY); /* 等待tPROG */
if (nand_wait_for_ready() != NSTA_READY)
{
return NSTA_ERROR; /* 失败 */
}
return 0; /* 成功 */
}
/**
* @brief 在NAND一页中的指定地址开始,写入指定长度的恒定数字
* @param pagenum : 要写入的页地址,范围:0~(block_pagenum*block_totalnum-1)
* @param colnum : 要写入的列开始地址(也就是页内地址),范围:0~(page_totalsize-1)
* @param cval : 要写入的指定常数
* @param numbytetowrite : 要写入的字节数(以4字节为单位)
* @retval 0,成功; 其他,错误代码
*/
uint8_t nand_write_pageconst(uint32_t pagenum, uint16_t colnum, uint32_t cval, uint16_t numbytetowrite)
{
uint16_t i = 0;
*(__IO uint8_t *)(NAND_ADDRESS | NAND_CMD) = NAND_WRITE0;
/* 发送地址 */
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)colnum;
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)(colnum >> 8);
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)pagenum;
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)(pagenum >> 8);
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)(pagenum >> 16);
nand_delay(NAND_TADL_DELAY); /* 等待tADL */
for (i = 0; i < numbytetowrite; i++) /* 写入数据,每次写4字节 */
{
*(__IO uint32_t *)NAND_ADDRESS = cval;
}
*(__IO uint8_t *)(NAND_ADDRESS | NAND_CMD) = NAND_WRITE_TURE1;
delay_us(NAND_TPROG_DELAY); /* 等待tPROG */
if (nand_wait_for_ready() != NSTA_READY)
{
return NSTA_ERROR; /* 失败 */
}
return 0; /* 成功 */
}
/**
* @brief 将一页数据拷贝到另一页,不写入新数据
* @note 源页和目的页要在同一个Plane内
* @param source_pagenum : 源页地址,范围:0~(block_pagenum*block_totalnum-1)
* @param dest_pagenum : 目的页地址,范围:0~(block_pagenum*block_totalnum-1)
* @retval 0,成功; 其他,错误代码
*/
uint8_t nand_copypage_withoutwrite(uint32_t source_pagenum, uint32_t dest_pagenum)
{
uint8_t res = 0;
uint16_t source_block = 0, dest_block = 0;
/* 判断源页和目的页是否在同一个plane中 */
source_block = source_pagenum / nand_dev.block_pagenum;
dest_block = dest_pagenum / nand_dev.block_pagenum;
if ((source_block % 2) != (dest_block % 2))
{
return NSTA_ERROR; /* 不在同一个plane内 */
}
*(__IO uint8_t *)(NAND_ADDRESS | NAND_CMD) = NAND_MOVEDATA_CMD0; /* 发送命令0X00 */
/* 发送源页地址 */
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)0;
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)0;
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)source_pagenum;
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)(source_pagenum >> 8);
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)(source_pagenum >> 16);
*(__IO uint8_t *)(NAND_ADDRESS | NAND_CMD) = NAND_MOVEDATA_CMD1; /* 发送命令0X35 */
/**
* 下面两行代码是等待R/B引脚变为低电平其实主要起延时作用的等待NAND操作R/B引脚。因为我们是通过
* 将STM32的NWAIT引脚(NAND的R/B引脚)配置为普通IO代码中通过读取NWAIT引脚的电平来判断NAND是否准备
* 就绪的。这个也就是模拟的方法所以在速度很快的时候有可能NAND还没来得及操作R/B引脚来表示NAND的忙
* 闲状态结果我们就读取了R/B引脚,这个时候肯定会出错的,事实上确实是会出错!大家也可以将下面两行
* 代码换成延时函数,只不过这里我们为了效率所以没有用延时函数。
*/
res = nand_waitrb(0); /* 等待RB=0 */
if (res)
{
return NSTA_TIMEOUT; /* 超时退出 */
}
/* 下面2行代码是真正判断NAND是否准备好的 */
res = nand_waitrb(1); /* 等待RB=1 */
if (res)
{
return NSTA_TIMEOUT; /* 超时退出 */
}
*(__IO uint8_t *)(NAND_ADDRESS | NAND_CMD) = NAND_MOVEDATA_CMD2; /* 发送命令0X85 */
/* 发送目的页地址 */
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)0;
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)0;
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)dest_pagenum;
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)(dest_pagenum >> 8);
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)(dest_pagenum >> 16);
*(__IO uint8_t *)(NAND_ADDRESS | NAND_CMD) = NAND_MOVEDATA_CMD3; /* 发送命令0X10 */
delay_us(NAND_TPROG_DELAY); /* 等待tPROG */
if (nand_wait_for_ready() != NSTA_READY)
{
return NSTA_ERROR; /* NAND未准备好 */
}
return 0; /* 成功 */
}
/**
* @brief 将一页数据拷贝到另一页,并且可以写入数据
* @note 源页和目的页要在同一个Plane内
* @param source_pagenum : 源页地址,范围:0~(block_pagenum*block_totalnum-1)
* @param dest_pagenum : 目的页地址,范围:0~(block_pagenum*block_totalnum-1)
* @param colnum : 页内列地址,范围:0~(page_totalsize-1)
* @param pbuffer : 要写入的数据
* @param numbytetowrite : 要写入的数据个数
* @retval 0,成功; 其他,错误代码
*/
uint8_t nand_copypage_withwrite(uint32_t source_pagenum, uint32_t dest_pagenum, uint16_t colnum, uint8_t *pbuffer, uint16_t numbytetowrite)
{
uint8_t res = 0;
__IO uint16_t i = 0;
uint16_t source_block = 0, dest_block = 0;
uint8_t eccnum = 0; /* 需要计算的ECC个数每NAND_ECC_SECTOR_SIZE字节计算一个ecc */
uint8_t eccstart = 0; /* 第一个ECC值所属的地址范围 */
/* 判断源页和目的页是否在同一个plane中 */
source_block = source_pagenum / nand_dev.block_pagenum;
dest_block = dest_pagenum / nand_dev.block_pagenum;
if ((source_block % 2) != (dest_block % 2))
{
return NSTA_ERROR; /* 不在同一个plane内 */
}
*(__IO uint8_t *)(NAND_ADDRESS | NAND_CMD) = NAND_MOVEDATA_CMD0; /* 发送命令0X00 */
/* 发送源页地址 */
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)0;
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)0;
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)source_pagenum;
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)(source_pagenum >> 8);
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)(source_pagenum >> 16);
*(__IO uint8_t *)(NAND_ADDRESS | NAND_CMD) = NAND_MOVEDATA_CMD1; /* 发送命令0X35 */
/**
* 下面两行代码是等待R/B引脚变为低电平其实主要起延时作用的等待NAND操作R/B引脚。因为我们是通过
* 将STM32的NWAIT引脚(NAND的R/B引脚)配置为普通IO代码中通过读取NWAIT引脚的电平来判断NAND是否准备
* 就绪的。这个也就是模拟的方法所以在速度很快的时候有可能NAND还没来得及操作R/B引脚来表示NAND的忙
* 闲状态结果我们就读取了R/B引脚,这个时候肯定会出错的,事实上确实是会出错!大家也可以将下面两行
* 代码换成延时函数,只不过这里我们为了效率所以没有用延时函数。
*/
res = nand_waitrb(0); /* 等待RB=0 */
if (res)
{
return NSTA_TIMEOUT; /* 超时退出 */
}
/* 下面2行代码是真正判断NAND是否准备好的 */
res = nand_waitrb(1); /* 等待RB=1 */
if (res)
{
return NSTA_TIMEOUT; /* 超时退出 */
}
*(__IO uint8_t *)(NAND_ADDRESS | NAND_CMD) = NAND_MOVEDATA_CMD2; /* 发送命令0X85 */
/* 发送目的页地址 */
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)colnum;
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)(colnum >> 8);
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)dest_pagenum;
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)(dest_pagenum >> 8);
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)(dest_pagenum >> 16);
/* 发送页内列地址 */
nand_delay(NAND_TADL_DELAY); /* 等待tADL */
if (numbytetowrite % NAND_ECC_SECTOR_SIZE) /* 不是NAND_ECC_SECTOR_SIZE的整数倍不进行ECC校验 */
{
for (i = 0; i < numbytetowrite; i++) /* 写入数据 */
{
*(__IO uint8_t *)NAND_ADDRESS = *(__IO uint8_t *)pbuffer++;
}
}
else
{
eccnum = numbytetowrite / NAND_ECC_SECTOR_SIZE; /* 得到ecc计算次数 */
eccstart = colnum / NAND_ECC_SECTOR_SIZE;
for (res = 0; res < eccnum; res++)
{
FMC_Bank3_R -> PCR |= 1 << 6; /* 使能ECC校验 */
for (i = 0; i < NAND_ECC_SECTOR_SIZE; i++) /* 写入NAND_ECC_SECTOR_SIZE个数据 */
{
*(__IO uint8_t *)NAND_ADDRESS = *(__IO uint8_t *)pbuffer++;
}
while (!(FMC_Bank3_R -> SR & (1 << 6))); /* 等待FIFO空 */
SCB_CleanInvalidateDCache(); /* 清除无效的D-Cache */
nand_dev.ecc_hdbuf[res + eccstart] = FMC_Bank3_R -> ECCR; /* 读取硬件计算后的ECC值 */
FMC_Bank3_R -> PCR &= ~(1 << 6); /* 禁止ECC校验 */
}
i = nand_dev.page_mainsize + 0X10 + eccstart * 4; /* 计算写入ECC的spare区地址 */
nand_delay(NAND_TADL_DELAY); /* 等待tADL */
*(__IO uint8_t *)(NAND_ADDRESS | NAND_CMD) = 0X85; /* 随机写指令 */
/* 发送地址 */
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)i;
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)(i >> 8);
nand_delay(NAND_TADL_DELAY); /* 等待tADL */
pbuffer = (uint8_t *)&nand_dev.ecc_hdbuf[eccstart];
for (i = 0; i < eccnum; i++) /* 写入ECC */
{
for (res = 0; res < 4; res++)
{
*(__IO uint8_t *)NAND_ADDRESS = *(__IO uint8_t *)pbuffer++;
}
}
}
*(__IO uint8_t *)(NAND_ADDRESS | NAND_CMD) = NAND_MOVEDATA_CMD3; /* 发送命令0X10 */
delay_us(NAND_TPROG_DELAY); /* 等待tPROG */
if (nand_wait_for_ready() != NSTA_READY)
{
return NSTA_ERROR; /* 失败 */
}
return 0; /* 成功 */
}
/**
* @brief 读取spare区中的数据
* @param pagenum : 要写入的页地址,范围:0~(block_pagenum*block_totalnum-1)
* @param colnum : 要写入的spare区地址(spare区中哪个地址),范围:0~(page_sparesize-1)
* @param pbuffer : 接收数据缓冲区
* @param numbytetoread : 要读取的字节数(不大于page_sparesize)
* @retval 0,成功; 其他,错误代码
*/
uint8_t nand_readspare(uint32_t pagenum, uint16_t colnum, uint8_t *pbuffer, uint16_t numbytetoread)
{
uint8_t temp = 0;
uint8_t remainbyte = 0;
remainbyte = nand_dev.page_sparesize - colnum;
if (numbytetoread > remainbyte)
{
numbytetoread = remainbyte; /* 确保要写入的字节数不大于spare剩余的大小 */
}
temp = nand_readpage(pagenum, colnum + nand_dev.page_mainsize, pbuffer, numbytetoread); /* 读取数据 */
return temp;
}
/**
* @brief 向spare区中写数据
* @param pagenum : 要写入的页地址,范围:0~(block_pagenum*block_totalnum-1)
* @param colnum : 要写入的spare区地址(spare区中哪个地址),范围:0~(page_sparesize-1)
* @param pbuffer : 要写入的数据首地址
* @param numbytetowrite : 要写入的字节数(不大于page_sparesize)
* @retval 0,成功; 其他,失败
*/
uint8_t nand_writespare(uint32_t pagenum, uint16_t colnum, uint8_t *pbuffer, uint16_t numbytetowrite)
{
uint8_t temp = 0;
uint8_t remainbyte = 0;
remainbyte = nand_dev.page_sparesize - colnum;
if (numbytetowrite > remainbyte)
{
numbytetowrite = remainbyte; /* 确保要读取的字节数不大于spare剩余的大小 */
}
temp = nand_writepage(pagenum, colnum + nand_dev.page_mainsize, pbuffer, numbytetowrite); /* 读取 */
return temp;
}
/**
* @brief 擦除一个块
* @param blocknum : 要擦除的BLOCK编号,范围:0-(block_totalnum-1)
* @retval 0,擦除成功; 其他,擦除失败
*/
uint8_t nand_eraseblock(uint32_t blocknum)
{
if (nand_dev.id == MT29F16G08ABABA)
{
blocknum <<= 7; /* 将块地址转换为页地址 */
}
else if (nand_dev.id == MT29F4G08ABADA)
{
blocknum <<= 6;
}
else if (nand_dev.id == FSNS8B004G)
{
blocknum <<= 6;
}
*(__IO uint8_t *)(NAND_ADDRESS | NAND_CMD) = NAND_ERASE0;
/* 发送块地址 */
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)blocknum;
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)(blocknum >> 8);
*(__IO uint8_t *)(NAND_ADDRESS | NAND_ADDR) = (uint8_t)(blocknum >> 16);
*(__IO uint8_t *)(NAND_ADDRESS | NAND_CMD) = NAND_ERASE1;
delay_ms(NAND_TBERS_DELAY); /* 等待擦除成功 */
if (nand_wait_for_ready() != NSTA_READY)
{
return NSTA_ERROR; /* 失败 */
}
return 0; /* 成功 */
}
/**
* @brief 全片擦除NAND FLASH
* @param 无
* @retval 无
*/
void nand_erasechip(void)
{
uint8_t status;
uint16_t i = 0;
for (i = 0; i < nand_dev.block_totalnum; i++) /* 循环擦除所有的块 */
{
status = nand_eraseblock(i);
if (status)
{
printf("Erase %d block fail!!,错误码为%d\r\n", i, status); /* 擦除失败 */
}
}
}
/**
* @brief 获取ECC的奇数位/偶数位
* @param oe : 0,偶数位; 1,奇数位
* @param eccval : 输入的ecc值
* @retval 计算后的ecc值(最多16位)
*/
uint16_t nand_ecc_get_oe(uint8_t oe, uint32_t eccval)
{
uint8_t i;
uint16_t ecctemp = 0;
for (i = 0; i < 24; i++)
{
if ((i % 2) == oe)
{
if ((eccval >> i) & 0X01)
{
ecctemp += 1 << (i >> 1);
}
}
}
return ecctemp;
}
/**
* @brief ECC校正函数
* @param data_buf : 数据缓存区
* @param eccrd : 读取出来, 原来保存的ECC值
* @param ecccl : 读取数据时, 硬件计算的ECC值
* @retval 0,错误已修正; 其他,ECC错误(有大于2个bit的错误,无法恢复)
*/
uint8_t nand_ecc_correction(uint8_t *data_buf, uint32_t eccrd, uint32_t ecccl)
{
uint16_t eccrdo, eccrde, eccclo, ecccle;
uint16_t eccchk = 0;
uint16_t errorpos = 0;
uint32_t bytepos = 0;
eccrdo = nand_ecc_get_oe(1, eccrd); /* 获取eccrd的奇数位 */
eccrde = nand_ecc_get_oe(0, eccrd); /* 获取eccrd的偶数位 */
eccclo = nand_ecc_get_oe(1, ecccl); /* 获取ecccl的奇数位 */
ecccle = nand_ecc_get_oe(0, ecccl); /* 获取ecccl的偶数位 */
eccchk = eccrdo ^ eccrde ^ eccclo ^ ecccle;
if (eccchk == 0XFFF) /* 全1,说明只有1bit ECC错误 */
{
errorpos = eccrdo ^ eccclo;
printf("errorpos:%d\r\n", errorpos);
bytepos = errorpos / 8;
data_buf[bytepos] ^= 1 << (errorpos % 8);
}
else /* 不是全1,说明至少有2bit ECC错误,无法修复 */
{
printf("2bit ecc error or more\r\n");
return 1;
}
return 0;
}

View File

@@ -1,137 +0,0 @@
/**
****************************************************************************************************
* @file nand.h
* @author 正点原子团队(ALIENTEK)
* @version V1.0
* @date 2022-09-06
* @brief NAND FLASH 驱动代码
* @license Copyright (c) 2020-2032, 广州市星翼电子科技有限公司
****************************************************************************************************
* @attention
*
* 实验平台:正点原子 阿波罗 H743开发板
* 在线视频:www.yuanzige.com
* 技术论坛:www.openedv.com
* 公司网址:www.alientek.com
* 购买地址:openedv.taobao.com
*
* 修改说明
* V1.0 20220906
* 第一次发布
*
****************************************************************************************************
*/
#ifndef _NAND_H
#define _NAND_H
#include "global.h"
/******************************************************************************************/
/* 引脚 定义 */
#define NAND_RB_GPIO_PORT GPIOD
#define NAND_RB_GPIO_PIN GPIO_PIN_6
#define NAND_RB_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOD_CLK_ENABLE(); }while(0) /* PD口时钟使能 */
/******************************************************************************************/
/* IO操作函数 */
#define NAND_RB HAL_GPIO_ReadPin(NAND_RB_GPIO_PORT, NAND_RB_GPIO_PIN) /* NAND Flash的闲/忙引脚 */
#define NAND_MAX_PAGE_SIZE 4096 /* 定义NAND FLASH的最大的PAGE大小不包括SPARE区默认4096字节 */
#define NAND_ECC_SECTOR_SIZE 512 /* 执行ECC计算的单元大小默认512字节 */
/* NAND FLASH操作相关延时函数 */
#define NAND_TADL_DELAY 30 /* tADL等待延迟,最少70ns */
#define NAND_TWHR_DELAY 25 /* tWHR等待延迟,最少60ns */
#define NAND_TRHW_DELAY 35 /* tRHW等待延迟,最少100ns */
#define NAND_TPROG_DELAY 200 /* tPROG等待延迟,典型值200us,最大需要700us */
#define NAND_TBERS_DELAY 4 /* tBERS等待延迟,典型值3.5ms,最大需要10ms */
/* NAND属性结构体 */
typedef struct
{
uint16_t page_totalsize; /* 每页总大小main区和spare区总和 */
uint16_t page_mainsize; /* 每页的main区大小 */
uint16_t page_sparesize; /* 每页的spare区大小 */
uint8_t block_pagenum; /* 每个块包含的页数量 */
uint16_t plane_blocknum; /* 每个plane包含的块数量 */
uint16_t block_totalnum; /* 总的块数量 */
uint16_t good_blocknum; /* 好块数量 */
uint16_t valid_blocknum; /* 有效块数量(供文件系统使用的好块数量) */
uint32_t id; /* NAND FLAS*(vu8*)(0X80000000|(1<<17))=CMD*(vu8*)(0X80000000|(1<<17))=CMDH ID */
uint16_t *lut; /* LUT表用作逻辑块-物理块转换 */
uint32_t ecc_hard; /* 硬件计算出来的ECC值 */
uint32_t ecc_hdbuf[NAND_MAX_PAGE_SIZE / NAND_ECC_SECTOR_SIZE]; /* ECC硬件计算值缓冲区 */
uint32_t ecc_rdbuf[NAND_MAX_PAGE_SIZE / NAND_ECC_SECTOR_SIZE]; /* ECC读取的值缓冲区 */
}nand_attriute;
extern nand_attriute nand_dev; /* nand重要参数结构体 */
#define NAND_ADDRESS 0X80000000 /* nand flash的访问地址,接NCE3,地址为:0X8000 0000 */
#define NAND_CMD 1 << 16 /* 发送命令 */
#define NAND_ADDR 1 << 17 /* 发送地址 */
/* NAND FLASH命令 */
#define nand_readID 0X90 /* 读ID指令 */
#define NAND_FEATURE 0XEF /* 设置特性指令 */
#define NAND_RESET 0XFF /* 复位NAND */
#define NAND_READSTA 0X70 /* 读状态 */
#define NAND_AREA_A 0X00
#define NAND_AREA_TRUE1 0X30
#define NAND_WRITE0 0X80
#define NAND_WRITE_TURE1 0X10
#define NAND_ERASE0 0X60
#define NAND_ERASE1 0XD0
#define NAND_MOVEDATA_CMD0 0X00
#define NAND_MOVEDATA_CMD1 0X35
#define NAND_MOVEDATA_CMD2 0X85
#define NAND_MOVEDATA_CMD3 0X10
/* NAND FLASH状态 */
#define NSTA_READY 0X40 /* nand已经准备好 */
#define NSTA_ERROR 0X01 /* nand错误 */
#define NSTA_TIMEOUT 0X02 /* 超时 */
#define NSTA_ECC1BITERR 0X03 /* ECC 1bit错误 */
#define NSTA_ECC2BITERR 0X04 /* ECC 2bit以上错误 */
/* NAND FLASH型号和对应的ID号 */
#define MT29F4G08ABADA 0XDC909556 /* MT29F4G08ABADA */
#define MT29F16G08ABABA 0X48002689 /* MT29F16G08ABABA */
#define FSNS8B004G 0XDC00A262 /* FSNS8B004G */
/******************************************************************************************/
uint8_t nand_init(void);
uint8_t nand_modeset(uint8_t mode);
void nand_mpu_config(void);
uint32_t nand_readid(void);
uint8_t nand_readstatus(void);
uint8_t nand_wait_for_ready(void);
uint8_t nand_reset(void);
uint8_t nand_waitrb(volatile uint8_t rb);
void nand_delay(volatile uint32_t i);
uint8_t nand_readpage(uint32_t pagenum, uint16_t colnum, uint8_t *pbuffer, uint16_t numbyte_to_read);
uint8_t nand_readpagecomp(uint32_t pagenum, uint16_t colnum, uint32_t cmpval, uint16_t numbyte_to_read, uint16_t *numbyte_equal);
uint8_t nand_writepage(uint32_t pagenum, uint16_t colnum, uint8_t *pbuffer, uint16_t numbyte_to_write);
uint8_t nand_write_pageconst(uint32_t pagenum, uint16_t colnum, uint32_t cval, uint16_t numbyte_to_write);
uint8_t nand_copypage_withoutwrite(uint32_t source_pagenum, uint32_t dest_pagenum);
uint8_t nand_copypage_withwrite(uint32_t source_pagenum, uint32_t dest_pagenum, uint16_t colnum, uint8_t *pbuffer, uint16_t numbyte_to_write);
uint8_t nand_readspare(uint32_t pagenum, uint16_t colnum, uint8_t *pbuffer, uint16_t numbyte_to_read);
uint8_t nand_writespare(uint32_t pagenum, uint16_t colnum, uint8_t *pbuffer, uint16_t numbyte_to_write);
uint8_t nand_eraseblock(uint32_t blocknum);
void nand_erasechip(void);
uint16_t nand_ecc_get_oe(uint8_t oe, uint32_t eccval);
uint8_t nand_ecc_correction(uint8_t *data_buf, uint32_t eccrd, uint32_t ecccl);
#endif

View File

@@ -1,239 +0,0 @@
/**
****************************************************************************************************
* @file nandtester.c
* @author 正点原子团队(ALIENTEK)
* @version V1.0
* @date 2022-09-06
* @brief NAND FLASH USMART测试代码
* @license Copyright (c) 2020-2032, 广州市星翼电子科技有限公司
****************************************************************************************************
* @attention
*
* 实验平台:正点原子 阿波罗 H743开发板
* 在线视频:www.yuanzige.com
* 技术论坛:www.openedv.com
* 公司网址:www.alientek.com
* 购买地址:openedv.taobao.com
*
* 修改说明
* V1.0 20220906
* 第一次发布
*
****************************************************************************************************
*/
#include "string.h"
#include "./BSP/NAND/ftl.h"
#include "./BSP/NAND/nand.h"
#include "./MALLOC/malloc.h"
#include "./SYSTEM/usart/usart.h"
#include "./BSP/NAND/nandtester.h"
/**
* @brief 向NAND某一页写入指定大小的数据
* @param pagenum:要写入的页地址
* @param colnum:要写入的开始列地址(页内地址)
* @param writebytes:要写入的数据大小MT29F16G最大为4320MT29F4G最大为2112
* @retval 0,检查成功,全部相等;1,检查失败,有不相等的情况
*/
uint8_t test_writepage(uint32_t pagenum, uint16_t colnum, uint16_t writebytes)
{
uint8_t *pbuf;
uint8_t sta = 0;
uint16_t i = 0;
pbuf = mymalloc(SRAMIN, 5000);
for (i = 0; i < writebytes; i++) /* 准备要写入的数据,填充数据,从0开始增大 */
{
pbuf[i] = i;
}
sta = nand_writepage(pagenum, colnum, pbuf, writebytes); /* 向nand写入数据 */
myfree(SRAMIN, pbuf); /* 释放内存 */
return sta;
}
/**
* @brief 读取NAND某一页指定大小的数据
* @param pagenum : 要读取的页地址
* @param colnum : 要读取的开始列地址(页内地址)
* @param readbytes : 要读取的数据大小MT29F16G最大为4320MT29F4G最大为2112
* @retval 操作结果
*/
uint8_t test_readpage(uint32_t pagenum, uint16_t colnum, uint16_t readbytes)
{
uint8_t *pbuf;
uint8_t sta = 0;
uint16_t i = 0;
pbuf = mymalloc(SRAMIN, 5000);
sta = nand_readpage(pagenum, colnum, pbuf, readbytes); /* 读取数据 */
if (sta == 0 || sta == NSTA_ECC1BITERR || sta == NSTA_ECC2BITERR) /* 读取成功 */
{
printf("read page data is:\r\n");
for (i = 0; i < readbytes; i++)
{
printf("%x ", pbuf[i]); /* 串口打印读取到的数据 */
}
printf("\r\nend\r\n");
}
myfree(SRAMIN, pbuf); /* 释放内存 */
return sta;
}
/**
* @brief 将一页数据拷贝到另外一页,并写入一部分内容.
* @note 源页和目标页要在同一个Plane内(同为奇数/同为偶数)
* @param spnum : 源页地址
* @param epnum : 目标页地址
* @param colnum : 要写入的开始列地址(页内地址)
* @param writebytes : 要写入的数据大小,不能超过页大小
* @retval 操作结果
*/
uint8_t test_copypageandwrite(uint32_t spnum, uint32_t dpnum, uint16_t colnum, uint16_t writebytes)
{
uint8_t *pbuf;
uint8_t sta = 0;
uint16_t i = 0;
pbuf = mymalloc(SRAMIN, 5000);
for (i = 0; i < writebytes; i++) /* 准备要写入的数据,填充数据,从0X80开始增大 */
{
pbuf[i] = i + 0X80;
}
sta = nand_copypage_withwrite(spnum, dpnum, colnum, pbuf, writebytes); /* 向nand写入数据 */
myfree(SRAMIN, pbuf); /* 释放内存 */
return sta;
}
/**
* @brief 读取NAND某一页Spare区指定大小的数据
* @param pagenum : 要读取的页地址
* @param colnum : 要读取的spare区开始地址
* @param readbytes : 要读取的数据大小MT29F16G最大为64MT29F4G最大为224
* @retval 操作结果
*/
uint8_t test_readspare(uint32_t pagenum, uint16_t colnum, uint16_t readbytes)
{
uint8_t *pbuf;
uint8_t sta = 0;
uint16_t i = 0;
pbuf = mymalloc(SRAMIN, 512);
sta = nand_readspare(pagenum, colnum, pbuf, readbytes); /* 读取数据 */
if (sta == 0) /* 读取成功 */
{
printf("read spare data is:\r\n");
for (i = 0; i < readbytes; i++)
{
printf("%x ", pbuf[i]); /* 串口打印读取到的数据 */
}
printf("\r\nend\r\n");
}
myfree(SRAMIN, pbuf); /* 释放内存 */
return sta;
}
/**
* @brief 从指定位置开始,读取整个NAND,每个BLOCK的第一个page的前5个字节
* @param sblock : 指定开始的block编号
* @retval 无
*/
void test_readallblockinfo(uint32_t sblock)
{
uint8_t j = 0;
uint32_t i = 0;
uint8_t sta;
uint8_t buffer[5];
for (i = sblock; i < nand_dev.block_totalnum; i++)
{
printf("block %d info:", i);
sta = nand_readspare(i * nand_dev.block_pagenum, 0, buffer, 5); /* 读取每个block,第一个page的前5个字节 */
if (sta)
{
printf("failed\r\n");
}
for (j = 0; j < 5; j++)
{
printf("%x ", buffer[j]);
}
printf("\r\n");
}
}
/******************************************************************************************/
/* FTL层测试代码 */
/**
* @brief 从某个扇区开始,写入seccnt个扇区的数据
* @param secx : 开始的扇区编号
* @param secsize : 扇区大小
* @param seccnt : 要写入的扇区个数
* @retval 操作结果
*/
uint8_t test_ftlwritesectors(uint32_t secx, uint16_t secsize, uint16_t seccnt)
{
uint8_t *pbuf;
uint8_t sta = 0;
uint32_t i = 0;
pbuf = mymalloc(SRAMIN, secsize * seccnt);
for (i = 0; i < secsize * seccnt; i++) /* 准备要写入的数据,填充数据,从0开始增大 */
{
pbuf[i] = i;
}
sta = ftl_write_sectors(pbuf, secx, secsize, seccnt); /* 向nand写入数据 */
myfree(SRAMIN, pbuf); /* 释放内存 */
return sta;
}
/**
* @brief 从某个扇区开始,读出seccnt个扇区的数据
* @param secx : 开始的扇区编号
* @param secsize : 扇区大小
* @param seccnt : 要读取的扇区个数
* @retval 操作结果
*/
uint8_t test_ftlreadsectors(uint32_t secx, uint16_t secsize, uint16_t seccnt)
{
uint8_t *pbuf;
uint8_t sta = 0;
uint32_t i = 0;
pbuf = mymalloc(SRAMIN, secsize * seccnt);
sta = ftl_read_sectors(pbuf, secx, secsize, seccnt); /* 读取数据 */
if (sta == 0)
{
printf("read sec %d data is:\r\n", secx);
for (i = 0; i < secsize * seccnt; i++) /* 准备要写入的数据,填充数据,从0开始增大 */
{
printf("%x ",pbuf[i]); /* 串口打印读取到的数据 */
}
printf("\r\nend\r\n");
}
myfree(SRAMIN, pbuf); /* 释放内存 */
return sta;
}

View File

@@ -1,40 +0,0 @@
/**
****************************************************************************************************
* @file nandtester.h
* @author 正点原子团队(ALIENTEK)
* @version V1.0
* @date 2022-09-06
* @brief NAND FLASH USMART测试代码
* @license Copyright (c) 2020-2032, 广州市星翼电子科技有限公司
****************************************************************************************************
* @attention
*
* 实验平台:正点原子 阿波罗 H743开发板
* 在线视频:www.yuanzige.com
* 技术论坛:www.openedv.com
* 公司网址:www.alientek.com
* 购买地址:openedv.taobao.com
*
* 修改说明
* V1.0 20220906
* 第一次发布
*
****************************************************************************************************
*/
#ifndef __NANDTESTER_H
#define __NANDTESTER_H
#include "./SYSTEM/sys/sys.h"
/******************************************************************************************/
uint8_t test_writepage(uint32_t pagenum, uint16_t colnum, uint16_t writebytes);
uint8_t test_readpage(uint32_t pagenum, uint16_t colnum, uint16_t readbytes);
uint8_t test_copypageandwrite(uint32_t spnum, uint32_t dpnum, uint16_t colnum, uint16_t writebytes);
uint8_t test_readspare(uint32_t pagenum, uint16_t colnum, uint16_t readbytes);
void test_readallblockinfo(uint32_t sblock);
uint8_t test_ftlwritesectors(uint32_t secx, uint16_t secsize, uint16_t seccnt);
uint8_t test_ftlreadsectors(uint32_t secx, uint16_t secsize, uint16_t seccnt);
#endif

View File

@@ -65,24 +65,6 @@ ETH.IPParameters=MediaInterface,TxDescAddress,RxDescAddress
ETH.MediaInterface=HAL_ETH_RMII_MODE ETH.MediaInterface=HAL_ETH_RMII_MODE
ETH.RxDescAddress=0x30040000 ETH.RxDescAddress=0x30040000
ETH.TxDescAddress=0x30040060 ETH.TxDescAddress=0x30040060
FMC.AttributeSpaceHiZSetupTime1=9
FMC.AttributeSpaceHoldSetupTime1=10
FMC.AttributeSpaceSetupTime1=9
FMC.AttributeSpaceWaitSetupTime1=9
FMC.CommonSpaceHiZSetupTime1=9
FMC.CommonSpaceHoldSetupTime1=10
FMC.CommonSpaceSetupTime1=9
FMC.CommonSpaceWaitSetupTime1=9
FMC.ECCPageSize1=FMC_NAND_ECC_PAGE_SIZE_512BYTE
FMC.IPParameters=TCLRSetupTime1,TARSetupTime1,ECCPageSize1,CommonSpaceSetupTime1,CommonSpaceWaitSetupTime1,CommonSpaceHoldSetupTime1,CommonSpaceHiZSetupTime1,AttributeSpaceSetupTime1,AttributeSpaceWaitSetupTime1,AttributeSpaceHoldSetupTime1,AttributeSpaceHiZSetupTime1,NandPageSize1,NandSpareAreaSize1,NandBlockSize1,NandBlockNbr1,NandPlaneNbr1,NandPlaneSize1
FMC.NandBlockNbr1=2048
FMC.NandBlockSize1=64
FMC.NandPageSize1=2048
FMC.NandPlaneNbr1=2
FMC.NandPlaneSize1=4096
FMC.NandSpareAreaSize1=64
FMC.TARSetupTime1=9
FMC.TCLRSetupTime1=9
FREERTOS.INCLUDE_uxTaskGetStackHighWaterMark=1 FREERTOS.INCLUDE_uxTaskGetStackHighWaterMark=1
FREERTOS.INCLUDE_vTaskDelayUntil=1 FREERTOS.INCLUDE_vTaskDelayUntil=1
FREERTOS.IPParameters=Tasks01,configENABLE_FPU,configUSE_COUNTING_SEMAPHORES,configTOTAL_HEAP_SIZE,configUSE_TICK_HOOK,configUSE_MALLOC_FAILED_HOOK,configGENERATE_RUN_TIME_STATS,configUSE_TRACE_FACILITY,configUSE_STATS_FORMATTING_FUNCTIONS,INCLUDE_vTaskDelayUntil,INCLUDE_uxTaskGetStackHighWaterMark,configMINIMAL_STACK_SIZE FREERTOS.IPParameters=Tasks01,configENABLE_FPU,configUSE_COUNTING_SEMAPHORES,configTOTAL_HEAP_SIZE,configUSE_TICK_HOOK,configUSE_MALLOC_FAILED_HOOK,configGENERATE_RUN_TIME_STATS,configUSE_TRACE_FACILITY,configUSE_STATS_FORMATTING_FUNCTIONS,INCLUDE_vTaskDelayUntil,INCLUDE_uxTaskGetStackHighWaterMark,configMINIMAL_STACK_SIZE
@@ -134,66 +116,51 @@ Mcu.CPN=STM32H743IIT6
Mcu.Family=STM32H7 Mcu.Family=STM32H7
Mcu.IP0=CORTEX_M7 Mcu.IP0=CORTEX_M7
Mcu.IP1=DEBUG Mcu.IP1=DEBUG
Mcu.IP10=SYS Mcu.IP10=USART1
Mcu.IP11=USART1 Mcu.IP11=USART3
Mcu.IP12=USART3 Mcu.IP12=USART6
Mcu.IP13=USART6
Mcu.IP2=DMA Mcu.IP2=DMA
Mcu.IP3=ETH Mcu.IP3=ETH
Mcu.IP4=FMC Mcu.IP4=FREERTOS
Mcu.IP5=FREERTOS Mcu.IP5=LWIP
Mcu.IP6=LWIP Mcu.IP6=MEMORYMAP
Mcu.IP7=MEMORYMAP Mcu.IP7=NVIC
Mcu.IP8=NVIC Mcu.IP8=RCC
Mcu.IP9=RCC Mcu.IP9=SYS
Mcu.IPNb=14 Mcu.IPNb=13
Mcu.Name=STM32H743IITx Mcu.Name=STM32H743IITx
Mcu.Package=LQFP176 Mcu.Package=LQFP176
Mcu.Pin0=PC14-OSC32_IN (OSC32_IN) Mcu.Pin0=PC14-OSC32_IN (OSC32_IN)
Mcu.Pin1=PC15-OSC32_OUT (OSC32_OUT) Mcu.Pin1=PC15-OSC32_OUT (OSC32_OUT)
Mcu.Pin10=PC4 Mcu.Pin10=PC4
Mcu.Pin11=PC5 Mcu.Pin11=PC5
Mcu.Pin12=PE7 Mcu.Pin12=PB10
Mcu.Pin13=PE8 Mcu.Pin13=PB11
Mcu.Pin14=PE9 Mcu.Pin14=PH12
Mcu.Pin15=PE10 Mcu.Pin15=PB12
Mcu.Pin16=PB10 Mcu.Pin16=PB13
Mcu.Pin17=PB11 Mcu.Pin17=PB14
Mcu.Pin18=PH12 Mcu.Pin18=PB15
Mcu.Pin19=PB12 Mcu.Pin19=PA13 (JTMS/SWDIO)
Mcu.Pin2=PH0-OSC_IN (PH0) Mcu.Pin2=PH0-OSC_IN (PH0)
Mcu.Pin20=PB13 Mcu.Pin20=PA14 (JTCK/SWCLK)
Mcu.Pin21=PB14 Mcu.Pin21=PC10
Mcu.Pin22=PB15 Mcu.Pin22=PC11
Mcu.Pin23=PD11 Mcu.Pin23=PC12
Mcu.Pin24=PD12 Mcu.Pin24=PG9
Mcu.Pin25=PD14 Mcu.Pin25=PG14
Mcu.Pin26=PD15 Mcu.Pin26=VP_FREERTOS_VS_CMSIS_V1
Mcu.Pin27=PC6 Mcu.Pin27=VP_LWIP_VS_Enabled
Mcu.Pin28=PC8 Mcu.Pin28=VP_SYS_VS_tim7
Mcu.Pin29=PA13 (JTMS/SWDIO) Mcu.Pin29=VP_MEMORYMAP_VS_MEMORYMAP
Mcu.Pin3=PH1-OSC_OUT (PH1) Mcu.Pin3=PH1-OSC_OUT (PH1)
Mcu.Pin30=PA14 (JTCK/SWCLK)
Mcu.Pin31=PC10
Mcu.Pin32=PC11
Mcu.Pin33=PC12
Mcu.Pin34=PD0
Mcu.Pin35=PD1
Mcu.Pin36=PD4
Mcu.Pin37=PD5
Mcu.Pin38=PG9
Mcu.Pin39=PG14
Mcu.Pin4=PC1 Mcu.Pin4=PC1
Mcu.Pin40=VP_FREERTOS_VS_CMSIS_V1
Mcu.Pin41=VP_LWIP_VS_Enabled
Mcu.Pin42=VP_SYS_VS_tim7
Mcu.Pin43=VP_MEMORYMAP_VS_MEMORYMAP
Mcu.Pin5=PA1 Mcu.Pin5=PA1
Mcu.Pin6=PA2 Mcu.Pin6=PA2
Mcu.Pin7=PH4 Mcu.Pin7=PH4
Mcu.Pin8=PH5 Mcu.Pin8=PH5
Mcu.Pin9=PA7 Mcu.Pin9=PA7
Mcu.PinsNb=44 Mcu.PinsNb=30
Mcu.ThirdPartyNb=0 Mcu.ThirdPartyNb=0
Mcu.UserConstants= Mcu.UserConstants=
Mcu.UserName=STM32H743IITx Mcu.UserName=STM32H743IITx
@@ -298,21 +265,6 @@ PC5.GPIOParameters=GPIO_Speed
PC5.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH PC5.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH
PC5.Mode=RMII PC5.Mode=RMII
PC5.Signal=ETH_RXD1 PC5.Signal=ETH_RXD1
PC6.Signal=FMC_NWAIT
PC8.Mode=NandChipSelect3_1
PC8.Signal=FMC_NCE
PD0.Signal=FMC_D2_DA2
PD1.Signal=FMC_D3_DA3
PD11.Signal=FMC_A16_CLE
PD12.Signal=FMC_A17_ALE
PD14.Signal=FMC_D0_DA0
PD15.Signal=FMC_D1_DA1
PD4.Signal=FMC_NOE
PD5.Signal=FMC_NWE
PE10.Signal=FMC_D7_DA7
PE7.Signal=FMC_D4_DA4
PE8.Signal=FMC_D5_DA5
PE9.Signal=FMC_D6_DA6
PG14.Locked=true PG14.Locked=true
PG14.Mode=Asynchronous PG14.Mode=Asynchronous
PG14.Signal=USART6_TX PG14.Signal=USART6_TX
@@ -455,32 +407,6 @@ RCC.VCO3OutputFreq_Value=100781250
RCC.VCOInput1Freq_Value=5000000 RCC.VCOInput1Freq_Value=5000000
RCC.VCOInput2Freq_Value=781250 RCC.VCOInput2Freq_Value=781250
RCC.VCOInput3Freq_Value=781250 RCC.VCOInput3Freq_Value=781250
SH.FMC_A16_CLE.0=FMC_CLE,8b-dmux1
SH.FMC_A16_CLE.ConfNb=1
SH.FMC_A17_ALE.0=FMC_ALE,8b-dmux1
SH.FMC_A17_ALE.ConfNb=1
SH.FMC_D0_DA0.0=FMC_D0,8b-dmux1
SH.FMC_D0_DA0.ConfNb=1
SH.FMC_D1_DA1.0=FMC_D1,8b-dmux1
SH.FMC_D1_DA1.ConfNb=1
SH.FMC_D2_DA2.0=FMC_D2,8b-dmux1
SH.FMC_D2_DA2.ConfNb=1
SH.FMC_D3_DA3.0=FMC_D3,8b-dmux1
SH.FMC_D3_DA3.ConfNb=1
SH.FMC_D4_DA4.0=FMC_D4,8b-dmux1
SH.FMC_D4_DA4.ConfNb=1
SH.FMC_D5_DA5.0=FMC_D5,8b-dmux1
SH.FMC_D5_DA5.ConfNb=1
SH.FMC_D6_DA6.0=FMC_D6,8b-dmux1
SH.FMC_D6_DA6.ConfNb=1
SH.FMC_D7_DA7.0=FMC_D7,8b-dmux1
SH.FMC_D7_DA7.ConfNb=1
SH.FMC_NOE.0=FMC_NOE,8b-dmux1
SH.FMC_NOE.ConfNb=1
SH.FMC_NWAIT.0=FMC_NWAIT,Wait1
SH.FMC_NWAIT.ConfNb=1
SH.FMC_NWE.0=FMC_NWE,8b-dmux1
SH.FMC_NWE.ConfNb=1
USART1.IPParameters=VirtualMode-Asynchronous USART1.IPParameters=VirtualMode-Asynchronous
USART1.VirtualMode-Asynchronous=VM_ASYNC USART1.VirtualMode-Asynchronous=VM_ASYNC
USART3.IPParameters=VirtualMode-Asynchronous USART3.IPParameters=VirtualMode-Asynchronous

View File

@@ -44,6 +44,23 @@ virtualFolder:
- path: ../Middlewares/Third_Party/LwIP/src/apps/http/fs.c - path: ../Middlewares/Third_Party/LwIP/src/apps/http/fs.c
- path: ../Middlewares/Third_Party/LwIP/src/apps/http/fsdata_custom.c - path: ../Middlewares/Third_Party/LwIP/src/apps/http/fsdata_custom.c
folders: [] folders: []
- name: USB
files: []
folders:
- name: App
files:
- path: ../USB_DEVICE/App/usb_device.c
- path: ../USB_DEVICE/App/usb_device.h
- path: ../USB_DEVICE/App/usbd_cdc_if.c
- path: ../USB_DEVICE/App/usbd_cdc_if.h
- path: ../USB_DEVICE/App/usbd_desc.c
- path: ../USB_DEVICE/App/usbd_desc.h
folders: []
- name: Target
files:
- path: ../USB_DEVICE/Target/usbd_conf.c
- path: ../USB_DEVICE/Target/usbd_conf.h
folders: []
- name: User - name: User
files: [] files: []
folders: folders:
@@ -107,6 +124,11 @@ virtualFolder:
- path: ../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_tim_ex.c - path: ../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_tim_ex.c
- path: ../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_uart.c - path: ../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_uart.c
- path: ../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_uart_ex.c - path: ../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_uart_ex.c
- path: ../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_pcd.c
- path: ../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_pcd_ex.c
- path: ../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_ll_usb.c
- path: ../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_nand.c
- path: ../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_ll_fmc.c
folders: [] folders: []
- name: CMSIS - name: CMSIS
files: files:
@@ -120,6 +142,20 @@ virtualFolder:
- path: ../Drivers/BSP/Components/yt8512c/yt8512c.c - path: ../Drivers/BSP/Components/yt8512c/yt8512c.c
- path: ../Drivers/BSP/Components/lan8742/lan8742.c - path: ../Drivers/BSP/Components/lan8742/lan8742.c
folders: [] folders: []
- name: STM32_USB_Device_Library
files: []
folders:
- name: Core
files:
- path: ../Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c
- path: ../Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c
- path: ../Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c
folders: []
- name: CDC
files:
- path: ../Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c
- path: ../Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc_if_template.c
folders: []
- name: Middlewares - name: Middlewares
files: [] files: []
folders: folders:
@@ -226,9 +262,6 @@ virtualFolder:
- path: ../Middlewares/Third_Party/Ykc/server_common.c - path: ../Middlewares/Third_Party/Ykc/server_common.c
- path: ../Middlewares/Third_Party/Ykc/server_to_charger.c - path: ../Middlewares/Third_Party/Ykc/server_to_charger.c
folders: [] folders: []
- name: Charger
files: []
folders: []
- name: cJSON - name: cJSON
files: files:
- path: ../Middlewares/Third_Party/cJSON/cJSON.c - path: ../Middlewares/Third_Party/cJSON/cJSON.c
@@ -284,9 +317,15 @@ targets:
- RTE/_IPort - RTE/_IPort
- ../Middlewares/Third_Party/Ykc - ../Middlewares/Third_Party/Ykc
- ../Middlewares/Third_Party/cJSON - ../Middlewares/Third_Party/cJSON
- ../USB_DEVICE/App
- ../USB_DEVICE/Target
- ../Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc
- ../Middlewares/ST/STM32_USB_Device_Library/Core/Inc
libList: [] libList: []
excludeList: excludeList:
- <virtual_root>/User/Hal/_hal_myi2c.c - <virtual_root>/User/Hal/_hal_myi2c.c
settings:
debugger: cortex-debug
toolchain: AC5 toolchain: AC5
toolchainConfigMap: toolchainConfigMap:
AC5: AC5:

View File

@@ -28,6 +28,12 @@
"editor.insertSpaces": true, "editor.insertSpaces": true,
"editor.tabSize": 4, "editor.tabSize": 4,
"editor.autoIndent": "advanced" "editor.autoIndent": "advanced"
},
"yaml.schemas": {
"file:///c%3A/Users/Administrator/.vscode/extensions/continue.continue-1.2.22-win32-x64/config-yaml-schema.json": [
".continue/**/*.yaml",
"file:///c%3A/Users/Administrator/.continue/config.yaml"
]
} }
}, },
"extensions": { "extensions": {

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?> <?xml version="1.0" encoding="UTF-8"?>
<ProjectOpt xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="project_optx.xsd"> <ProjectOpt xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="project_optx.xsd">
<SchemaVersion>1.0</SchemaVersion> <SchemaVersion>1.0</SchemaVersion>
@@ -45,7 +45,7 @@
<PageWidth>79</PageWidth> <PageWidth>79</PageWidth>
<PageLength>66</PageLength> <PageLength>66</PageLength>
<TabStop>8</TabStop> <TabStop>8</TabStop>
<ListingPath></ListingPath> <ListingPath />
</OPTLEX> </OPTLEX>
<ListingPage> <ListingPage>
<CreateCListing>1</CreateCListing> <CreateCListing>1</CreateCListing>
@@ -104,16 +104,16 @@
<bSchkAxf>0</bSchkAxf> <bSchkAxf>0</bSchkAxf>
<bTchkAxf>0</bTchkAxf> <bTchkAxf>0</bTchkAxf>
<nTsel>3</nTsel> <nTsel>3</nTsel>
<sDll></sDll> <sDll />
<sDllPa></sDllPa> <sDllPa />
<sDlgDll></sDlgDll> <sDlgDll />
<sDlgPa></sDlgPa> <sDlgPa />
<sIfile></sIfile> <sIfile />
<tDll></tDll> <tDll />
<tDllPa></tDllPa> <tDllPa />
<tDlgDll></tDlgDll> <tDlgDll />
<tDlgPa></tDlgPa> <tDlgPa />
<tIfile></tIfile> <tIfile />
<pMon>BIN\CMSIS_AGDI.dll</pMon> <pMon>BIN\CMSIS_AGDI.dll</pMon>
</DebugOpt> </DebugOpt>
<TargetDriverDllRegistry> <TargetDriverDllRegistry>
@@ -135,12 +135,12 @@
<SetRegEntry> <SetRegEntry>
<Number>0</Number> <Number>0</Number>
<Key>ARMDBGFLAGS</Key> <Key>ARMDBGFLAGS</Key>
<Name></Name> <Name />
</SetRegEntry> </SetRegEntry>
<SetRegEntry> <SetRegEntry>
<Number>0</Number> <Number>0</Number>
<Key>DLGUARM</Key> <Key>DLGUARM</Key>
<Name></Name> <Name />
</SetRegEntry> </SetRegEntry>
<SetRegEntry> <SetRegEntry>
<Number>0</Number> <Number>0</Number>
@@ -158,7 +158,7 @@
<Name>-U-O142 -O2254 -S0 -C0 -N00("ARM CoreSight SW-DP") -D00(5BA02477) -L00(0) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD20000000 -FC1000 -FN1 -FF0STM32H7x_2048.FLM -FS08000000 -FL0200000 -FP0($$Device:STM32H743IITx$CMSIS\Flash\STM32H7x_2048.FLM)</Name> <Name>-U-O142 -O2254 -S0 -C0 -N00("ARM CoreSight SW-DP") -D00(5BA02477) -L00(0) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD20000000 -FC1000 -FN1 -FF0STM32H7x_2048.FLM -FS08000000 -FL0200000 -FP0($$Device:STM32H743IITx$CMSIS\Flash\STM32H7x_2048.FLM)</Name>
</SetRegEntry> </SetRegEntry>
</TargetDriverDllRegistry> </TargetDriverDllRegistry>
<Breakpoint/> <Breakpoint />
<WatchWindow1> <WatchWindow1>
<Ww> <Ww>
<count>0</count> <count>0</count>
@@ -235,19 +235,19 @@
<newCpu>0</newCpu> <newCpu>0</newCpu>
<uProt>0</uProt> <uProt>0</uProt>
</DebugFlag> </DebugFlag>
<LintExecutable></LintExecutable> <LintExecutable />
<LintConfigFile></LintConfigFile> <LintConfigFile />
<bLintAuto>0</bLintAuto> <bLintAuto>0</bLintAuto>
<bAutoGenD>0</bAutoGenD> <bAutoGenD>0</bAutoGenD>
<LntExFlags>0</LntExFlags> <LntExFlags>0</LntExFlags>
<pMisraName></pMisraName> <pMisraName />
<pszMrule></pszMrule> <pszMrule />
<pSingCmds></pSingCmds> <pSingCmds />
<pMultCmds></pMultCmds> <pMultCmds />
<pMisraNamep></pMisraNamep> <pMisraNamep />
<pszMrulep></pszMrulep> <pszMrulep />
<pSingCmdsp></pSingCmdsp> <pSingCmdsp />
<pMultCmdsp></pMultCmdsp> <pMultCmdsp />
<DebugDescription> <DebugDescription>
<Enable>1</Enable> <Enable>1</Enable>
<EnableFlashSeq>1</EnableFlashSeq> <EnableFlashSeq>1</EnableFlashSeq>

View File

@@ -1,10 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?> <?xml version="1.0" encoding="UTF-8"?>
<Project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="project_projx.xsd"> <Project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" noNamespaceSchemaLocation="project_projx.xsd">
<SchemaVersion>2.1</SchemaVersion> <SchemaVersion>2.1</SchemaVersion>
<Header>### uVision Project, (C) Keil Software</Header> <Header>### uVision Project, (C) Keil Software</Header>
<Targets> <Targets>
<Target> <Target>
<TargetName>IPort</TargetName> <TargetName>IPort</TargetName>
@@ -20,28 +17,28 @@
<PackID>Keil.STM32H7xx_DFP.3.0.0</PackID> <PackID>Keil.STM32H7xx_DFP.3.0.0</PackID>
<PackURL>http://www.keil.com/pack/</PackURL> <PackURL>http://www.keil.com/pack/</PackURL>
<Cpu>IRAM(0x20000000-0x2001FFFF) IRAM2(0x24000000-0x2407FFFF) IROM(0x8000000-0x81FFFFF) CLOCK(12000000) FPU3(DFPU) CPUTYPE("Cortex-M7") ELITTLE TZ</Cpu> <Cpu>IRAM(0x20000000-0x2001FFFF) IRAM2(0x24000000-0x2407FFFF) IROM(0x8000000-0x81FFFFF) CLOCK(12000000) FPU3(DFPU) CPUTYPE("Cortex-M7") ELITTLE TZ</Cpu>
<FlashUtilSpec></FlashUtilSpec> <FlashUtilSpec />
<StartupFile></StartupFile> <StartupFile />
<FlashDriverDll></FlashDriverDll> <FlashDriverDll />
<DeviceId>0</DeviceId> <DeviceId>0</DeviceId>
<RegisterFile></RegisterFile> <RegisterFile />
<MemoryEnv></MemoryEnv> <MemoryEnv />
<Cmp></Cmp> <Cmp />
<Asm></Asm> <Asm />
<Linker></Linker> <Linker />
<OHString></OHString> <OHString />
<InfinionOptionDll></InfinionOptionDll> <InfinionOptionDll />
<SLE66CMisc></SLE66CMisc> <SLE66CMisc />
<SLE66AMisc></SLE66AMisc> <SLE66AMisc />
<SLE66LinkerMisc></SLE66LinkerMisc> <SLE66LinkerMisc />
<SFDFile>$$Device:STM32H743IITx$CMSIS\SVD\STM32H743.svd</SFDFile> <SFDFile>$$Device:STM32H743IITx$CMSIS\SVD\STM32H743.svd</SFDFile>
<bCustSvd>0</bCustSvd> <bCustSvd>0</bCustSvd>
<UseEnv>0</UseEnv> <UseEnv>0</UseEnv>
<BinPath></BinPath> <BinPath />
<IncludePath></IncludePath> <IncludePath />
<LibPath></LibPath> <LibPath />
<RegisterFilePath></RegisterFilePath> <RegisterFilePath />
<DBRegisterFilePath></DBRegisterFilePath> <DBRegisterFilePath />
<TargetStatus> <TargetStatus>
<Error>0</Error> <Error>0</Error>
<ExitCodeStop>0</ExitCodeStop> <ExitCodeStop>0</ExitCodeStop>
@@ -56,15 +53,15 @@
<CreateHexFile>1</CreateHexFile> <CreateHexFile>1</CreateHexFile>
<DebugInformation>1</DebugInformation> <DebugInformation>1</DebugInformation>
<BrowseInformation>0</BrowseInformation> <BrowseInformation>0</BrowseInformation>
<ListingPath></ListingPath> <ListingPath />
<HexFormatSelection>1</HexFormatSelection> <HexFormatSelection>1</HexFormatSelection>
<Merge32K>0</Merge32K> <Merge32K>0</Merge32K>
<CreateBatchFile>0</CreateBatchFile> <CreateBatchFile>0</CreateBatchFile>
<BeforeCompile> <BeforeCompile>
<RunUserProg1>0</RunUserProg1> <RunUserProg1>0</RunUserProg1>
<RunUserProg2>0</RunUserProg2> <RunUserProg2>0</RunUserProg2>
<UserProg1Name></UserProg1Name> <UserProg1Name />
<UserProg2Name></UserProg2Name> <UserProg2Name />
<UserProg1Dos16Mode>0</UserProg1Dos16Mode> <UserProg1Dos16Mode>0</UserProg1Dos16Mode>
<UserProg2Dos16Mode>0</UserProg2Dos16Mode> <UserProg2Dos16Mode>0</UserProg2Dos16Mode>
<nStopU1X>0</nStopU1X> <nStopU1X>0</nStopU1X>
@@ -73,8 +70,8 @@
<BeforeMake> <BeforeMake>
<RunUserProg1>0</RunUserProg1> <RunUserProg1>0</RunUserProg1>
<RunUserProg2>0</RunUserProg2> <RunUserProg2>0</RunUserProg2>
<UserProg1Name></UserProg1Name> <UserProg1Name />
<UserProg2Name></UserProg2Name> <UserProg2Name />
<UserProg1Dos16Mode>0</UserProg1Dos16Mode> <UserProg1Dos16Mode>0</UserProg1Dos16Mode>
<UserProg2Dos16Mode>0</UserProg2Dos16Mode> <UserProg2Dos16Mode>0</UserProg2Dos16Mode>
<nStopB1X>0</nStopB1X> <nStopB1X>0</nStopB1X>
@@ -83,15 +80,15 @@
<AfterMake> <AfterMake>
<RunUserProg1>0</RunUserProg1> <RunUserProg1>0</RunUserProg1>
<RunUserProg2>1</RunUserProg2> <RunUserProg2>1</RunUserProg2>
<UserProg1Name></UserProg1Name> <UserProg1Name />
<UserProg2Name></UserProg2Name> <UserProg2Name />
<UserProg1Dos16Mode>0</UserProg1Dos16Mode> <UserProg1Dos16Mode>0</UserProg1Dos16Mode>
<UserProg2Dos16Mode>0</UserProg2Dos16Mode> <UserProg2Dos16Mode>0</UserProg2Dos16Mode>
<nStopA1X>0</nStopA1X> <nStopA1X>0</nStopA1X>
<nStopA2X>0</nStopA2X> <nStopA2X>0</nStopA2X>
</AfterMake> </AfterMake>
<SelectedForBatchBuild>1</SelectedForBatchBuild> <SelectedForBatchBuild>1</SelectedForBatchBuild>
<SVCSIdString></SVCSIdString> <SVCSIdString />
</TargetCommonOption> </TargetCommonOption>
<CommonProperty> <CommonProperty>
<UseCPPCompiler>0</UseCPPCompiler> <UseCPPCompiler>0</UseCPPCompiler>
@@ -105,8 +102,8 @@
<AssembleAssemblyFile>0</AssembleAssemblyFile> <AssembleAssemblyFile>0</AssembleAssemblyFile>
<PublicsOnly>0</PublicsOnly> <PublicsOnly>0</PublicsOnly>
<StopOnExitCode>3</StopOnExitCode> <StopOnExitCode>3</StopOnExitCode>
<CustomArgument></CustomArgument> <CustomArgument />
<IncludeLibraryModules></IncludeLibraryModules> <IncludeLibraryModules />
<ComprImg>0</ComprImg> <ComprImg>0</ComprImg>
</CommonProperty> </CommonProperty>
<DllOption> <DllOption>
@@ -139,11 +136,11 @@
</Flash1> </Flash1>
<bUseTDR>1</bUseTDR> <bUseTDR>1</bUseTDR>
<Flash2>BIN\UL2V8M.DLL</Flash2> <Flash2>BIN\UL2V8M.DLL</Flash2>
<Flash3></Flash3> <Flash3 />
<Flash4></Flash4> <Flash4 />
<pFcarmOut></pFcarmOut> <pFcarmOut />
<pFcarmGrp></pFcarmGrp> <pFcarmGrp />
<pFcArmRoot></pFcArmRoot> <pFcArmRoot />
<FcArmLst>0</FcArmLst> <FcArmLst>0</FcArmLst>
</Utilities> </Utilities>
<TargetArmAds> <TargetArmAds>
@@ -176,7 +173,7 @@
<RvctClst>0</RvctClst> <RvctClst>0</RvctClst>
<GenPPlst>0</GenPPlst> <GenPPlst>0</GenPPlst>
<AdsCpuType>"Cortex-M7"</AdsCpuType> <AdsCpuType>"Cortex-M7"</AdsCpuType>
<RvctDeviceName></RvctDeviceName> <RvctDeviceName />
<mOS>0</mOS> <mOS>0</mOS>
<uocRom>0</uocRom> <uocRom>0</uocRom>
<uocRam>0</uocRam> <uocRam>0</uocRam>
@@ -310,7 +307,7 @@
<Size>0x80000</Size> <Size>0x80000</Size>
</OCR_RVCT10> </OCR_RVCT10>
</OnChipMemories> </OnChipMemories>
<RvctStartVector></RvctStartVector> <RvctStartVector />
</ArmAdsMisc> </ArmAdsMisc>
<Cads> <Cads>
<interw>1</interw> <interw>1</interw>
@@ -337,9 +334,9 @@
<v6WtE>0</v6WtE> <v6WtE>0</v6WtE>
<v6Rtti>0</v6Rtti> <v6Rtti>0</v6Rtti>
<VariousControls> <VariousControls>
<MiscControls></MiscControls> <MiscControls />
<Define>USE_HAL_DRIVER,STM32H743xx</Define> <Define>USE_HAL_DRIVER,STM32H743xx</Define>
<Undefine></Undefine> <Undefine />
<IncludePath>../Core/Inc;../Drivers/STM32H7xx_HAL_Driver/Inc;../Drivers/STM32H7xx_HAL_Driver/Inc/Legacy;../Drivers/CMSIS/Device/ST/STM32H7xx/Include;../Drivers/CMSIS/Include;../User/Global;../Middlewares/Third_Party/FreeRTOS/Source/include;../Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS;../Middlewares/Third_Party/FreeRTOS/Source/portable/RVDS/ARM_CM4F;../User/Driver;../User/Hal;../User/Task;../User/Os;../LWIP/App;../LWIP/Target;../Middlewares/Third_Party/LwIP/src/include;../Middlewares/Third_Party/LwIP/system;../Drivers/BSP/Components/lan8742;../Middlewares/Third_Party/LwIP/src/include/netif/ppp;../Middlewares/Third_Party/LwIP/src/include/lwip;../Middlewares/Third_Party/LwIP/src/include/lwip/apps;../Middlewares/Third_Party/LwIP/src/include/lwip/priv;../Middlewares/Third_Party/LwIP/src/include/lwip/prot;../Middlewares/Third_Party/LwIP/src/include/netif;../Middlewares/Third_Party/LwIP/src/include/compat/posix;../Middlewares/Third_Party/LwIP/src/include/compat/posix/arpa;../Middlewares/Third_Party/LwIP/src/include/compat/posix/net;../Middlewares/Third_Party/LwIP/src/include/compat/posix/sys;../Middlewares/Third_Party/LwIP/src/include/compat/stdc;../Middlewares/Third_Party/LwIP/system/arch;../Drivers/BSP/Components/yt8512c;../Middlewares/Third_Party/Ykc;../Middlewares/Third_Party/easydb/inc</IncludePath> <IncludePath>../Core/Inc;../Drivers/STM32H7xx_HAL_Driver/Inc;../Drivers/STM32H7xx_HAL_Driver/Inc/Legacy;../Drivers/CMSIS/Device/ST/STM32H7xx/Include;../Drivers/CMSIS/Include;../User/Global;../Middlewares/Third_Party/FreeRTOS/Source/include;../Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS;../Middlewares/Third_Party/FreeRTOS/Source/portable/RVDS/ARM_CM4F;../User/Driver;../User/Hal;../User/Task;../User/Os;../LWIP/App;../LWIP/Target;../Middlewares/Third_Party/LwIP/src/include;../Middlewares/Third_Party/LwIP/system;../Drivers/BSP/Components/lan8742;../Middlewares/Third_Party/LwIP/src/include/netif/ppp;../Middlewares/Third_Party/LwIP/src/include/lwip;../Middlewares/Third_Party/LwIP/src/include/lwip/apps;../Middlewares/Third_Party/LwIP/src/include/lwip/priv;../Middlewares/Third_Party/LwIP/src/include/lwip/prot;../Middlewares/Third_Party/LwIP/src/include/netif;../Middlewares/Third_Party/LwIP/src/include/compat/posix;../Middlewares/Third_Party/LwIP/src/include/compat/posix/arpa;../Middlewares/Third_Party/LwIP/src/include/compat/posix/net;../Middlewares/Third_Party/LwIP/src/include/compat/posix/sys;../Middlewares/Third_Party/LwIP/src/include/compat/stdc;../Middlewares/Third_Party/LwIP/system/arch;../Drivers/BSP/Components/yt8512c;../Middlewares/Third_Party/Ykc;../Middlewares/Third_Party/easydb/inc</IncludePath>
</VariousControls> </VariousControls>
</Cads> </Cads>
@@ -355,9 +352,9 @@
<useXO>0</useXO> <useXO>0</useXO>
<ClangAsOpt>1</ClangAsOpt> <ClangAsOpt>1</ClangAsOpt>
<VariousControls> <VariousControls>
<MiscControls></MiscControls> <MiscControls />
<Define></Define> <Define />
<Undefine></Undefine> <Undefine />
<IncludePath>../Core/Inc</IncludePath> <IncludePath>../Core/Inc</IncludePath>
</VariousControls> </VariousControls>
</Aads> </Aads>
@@ -368,15 +365,15 @@
<noStLib>0</noStLib> <noStLib>0</noStLib>
<RepFail>1</RepFail> <RepFail>1</RepFail>
<useFile>0</useFile> <useFile>0</useFile>
<TextAddressRange></TextAddressRange> <TextAddressRange />
<DataAddressRange></DataAddressRange> <DataAddressRange />
<pXoBase></pXoBase> <pXoBase />
<ScatterFile></ScatterFile> <ScatterFile />
<IncludeLibs></IncludeLibs> <IncludeLibs />
<IncludeLibsPath></IncludeLibsPath> <IncludeLibsPath />
<Misc></Misc> <Misc />
<LinkerInputFile></LinkerInputFile> <LinkerInputFile />
<DisabledWarnings></DisabledWarnings> <DisabledWarnings />
</LDads> </LDads>
</TargetArmAds> </TargetArmAds>
</TargetOption> </TargetOption>
@@ -414,62 +411,6 @@
<FileType>1</FileType> <FileType>1</FileType>
<FilePath>../Core/Src/dma.c</FilePath> <FilePath>../Core/Src/dma.c</FilePath>
</File> </File>
<File>
<FileName>fmc.c</FileName>
<FileType>1</FileType>
<FilePath>../Core/Src/fmc.c</FilePath>
<FileOption>
<CommonProperty>
<UseCPPCompiler>2</UseCPPCompiler>
<RVCTCodeConst>0</RVCTCodeConst>
<RVCTZI>0</RVCTZI>
<RVCTOtherData>0</RVCTOtherData>
<ModuleSelection>0</ModuleSelection>
<IncludeInBuild>1</IncludeInBuild>
<AlwaysBuild>2</AlwaysBuild>
<GenerateAssemblyFile>2</GenerateAssemblyFile>
<AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg>
</CommonProperty>
<FileArmAds>
<Cads>
<interw>2</interw>
<Optim>0</Optim>
<oTime>2</oTime>
<SplitLS>2</SplitLS>
<OneElfS>2</OneElfS>
<Strict>2</Strict>
<EnumInt>2</EnumInt>
<PlainCh>2</PlainCh>
<Ropi>2</Ropi>
<Rwpi>2</Rwpi>
<wLevel>0</wLevel>
<uThumb>2</uThumb>
<uSurpInc>2</uSurpInc>
<uC99>2</uC99>
<uGnu>2</uGnu>
<useXO>2</useXO>
<v6Lang>0</v6Lang>
<v6LangP>0</v6LangP>
<vShortEn>2</vShortEn>
<vShortWch>2</vShortWch>
<v6Lto>2</v6Lto>
<v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
<File> <File>
<FileName>memorymap.c</FileName> <FileName>memorymap.c</FileName>
<FileType>1</FileType> <FileType>1</FileType>
@@ -487,8 +428,6 @@
<AssembleAssemblyFile>2</AssembleAssemblyFile> <AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly> <PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode> <StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg> <ComprImg>1</ComprImg>
</CommonProperty> </CommonProperty>
<FileArmAds> <FileArmAds>
@@ -516,12 +455,6 @@
<v6Lto>2</v6Lto> <v6Lto>2</v6Lto>
<v6WtE>2</v6WtE> <v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti> <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads> </Cads>
</FileArmAds> </FileArmAds>
</FileOption> </FileOption>
@@ -746,118 +679,6 @@
<FileType>1</FileType> <FileType>1</FileType>
<FilePath>../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_exti.c</FilePath> <FilePath>../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_exti.c</FilePath>
</File> </File>
<File>
<FileName>stm32h7xx_ll_fmc.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_ll_fmc.c</FilePath>
<FileOption>
<CommonProperty>
<UseCPPCompiler>2</UseCPPCompiler>
<RVCTCodeConst>0</RVCTCodeConst>
<RVCTZI>0</RVCTZI>
<RVCTOtherData>0</RVCTOtherData>
<ModuleSelection>0</ModuleSelection>
<IncludeInBuild>1</IncludeInBuild>
<AlwaysBuild>2</AlwaysBuild>
<GenerateAssemblyFile>2</GenerateAssemblyFile>
<AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg>
</CommonProperty>
<FileArmAds>
<Cads>
<interw>2</interw>
<Optim>0</Optim>
<oTime>2</oTime>
<SplitLS>2</SplitLS>
<OneElfS>2</OneElfS>
<Strict>2</Strict>
<EnumInt>2</EnumInt>
<PlainCh>2</PlainCh>
<Ropi>2</Ropi>
<Rwpi>2</Rwpi>
<wLevel>0</wLevel>
<uThumb>2</uThumb>
<uSurpInc>2</uSurpInc>
<uC99>2</uC99>
<uGnu>2</uGnu>
<useXO>2</useXO>
<v6Lang>0</v6Lang>
<v6LangP>0</v6LangP>
<vShortEn>2</vShortEn>
<vShortWch>2</vShortWch>
<v6Lto>2</v6Lto>
<v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
<File>
<FileName>stm32h7xx_hal_nand.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_nand.c</FilePath>
<FileOption>
<CommonProperty>
<UseCPPCompiler>2</UseCPPCompiler>
<RVCTCodeConst>0</RVCTCodeConst>
<RVCTZI>0</RVCTZI>
<RVCTOtherData>0</RVCTOtherData>
<ModuleSelection>0</ModuleSelection>
<IncludeInBuild>1</IncludeInBuild>
<AlwaysBuild>2</AlwaysBuild>
<GenerateAssemblyFile>2</GenerateAssemblyFile>
<AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg>
</CommonProperty>
<FileArmAds>
<Cads>
<interw>2</interw>
<Optim>0</Optim>
<oTime>2</oTime>
<SplitLS>2</SplitLS>
<OneElfS>2</OneElfS>
<Strict>2</Strict>
<EnumInt>2</EnumInt>
<PlainCh>2</PlainCh>
<Ropi>2</Ropi>
<Rwpi>2</Rwpi>
<wLevel>0</wLevel>
<uThumb>2</uThumb>
<uSurpInc>2</uSurpInc>
<uC99>2</uC99>
<uGnu>2</uGnu>
<useXO>2</useXO>
<v6Lang>0</v6Lang>
<v6LangP>0</v6LangP>
<vShortEn>2</vShortEn>
<vShortWch>2</vShortWch>
<v6Lto>2</v6Lto>
<v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads>
</FileArmAds>
</FileOption>
</File>
<File> <File>
<FileName>stm32h7xx_hal_tim.c</FileName> <FileName>stm32h7xx_hal_tim.c</FileName>
<FileType>1</FileType> <FileType>1</FileType>
@@ -905,8 +726,6 @@
<AssembleAssemblyFile>2</AssembleAssemblyFile> <AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly> <PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode> <StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg> <ComprImg>1</ComprImg>
</CommonProperty> </CommonProperty>
<GroupArmAds> <GroupArmAds>
@@ -934,12 +753,6 @@
<v6Lto>2</v6Lto> <v6Lto>2</v6Lto>
<v6WtE>2</v6WtE> <v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti> <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads> </Cads>
<Aads> <Aads>
<interw>2</interw> <interw>2</interw>
@@ -952,12 +765,6 @@
<uSurpInc>2</uSurpInc> <uSurpInc>2</uSurpInc>
<useXO>2</useXO> <useXO>2</useXO>
<ClangAsOpt>1</ClangAsOpt> <ClangAsOpt>1</ClangAsOpt>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Aads> </Aads>
</GroupArmAds> </GroupArmAds>
</GroupOption> </GroupOption>
@@ -1029,8 +836,6 @@
<AssembleAssemblyFile>2</AssembleAssemblyFile> <AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly> <PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode> <StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg> <ComprImg>1</ComprImg>
</CommonProperty> </CommonProperty>
<GroupArmAds> <GroupArmAds>
@@ -1058,12 +863,6 @@
<v6Lto>2</v6Lto> <v6Lto>2</v6Lto>
<v6WtE>2</v6WtE> <v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti> <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads> </Cads>
<Aads> <Aads>
<interw>2</interw> <interw>2</interw>
@@ -1076,12 +875,6 @@
<uSurpInc>2</uSurpInc> <uSurpInc>2</uSurpInc>
<useXO>2</useXO> <useXO>2</useXO>
<ClangAsOpt>1</ClangAsOpt> <ClangAsOpt>1</ClangAsOpt>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Aads> </Aads>
</GroupArmAds> </GroupArmAds>
</GroupOption> </GroupOption>
@@ -1108,8 +901,6 @@
<AssembleAssemblyFile>2</AssembleAssemblyFile> <AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly> <PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode> <StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg> <ComprImg>1</ComprImg>
</CommonProperty> </CommonProperty>
<GroupArmAds> <GroupArmAds>
@@ -1137,12 +928,6 @@
<v6Lto>2</v6Lto> <v6Lto>2</v6Lto>
<v6WtE>2</v6WtE> <v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti> <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads> </Cads>
<Aads> <Aads>
<interw>2</interw> <interw>2</interw>
@@ -1155,12 +940,6 @@
<uSurpInc>2</uSurpInc> <uSurpInc>2</uSurpInc>
<useXO>2</useXO> <useXO>2</useXO>
<ClangAsOpt>1</ClangAsOpt> <ClangAsOpt>1</ClangAsOpt>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Aads> </Aads>
</GroupArmAds> </GroupArmAds>
</GroupOption> </GroupOption>
@@ -1187,8 +966,6 @@
<AssembleAssemblyFile>2</AssembleAssemblyFile> <AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly> <PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode> <StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg> <ComprImg>1</ComprImg>
</CommonProperty> </CommonProperty>
<GroupArmAds> <GroupArmAds>
@@ -1216,12 +993,6 @@
<v6Lto>2</v6Lto> <v6Lto>2</v6Lto>
<v6WtE>2</v6WtE> <v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti> <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads> </Cads>
<Aads> <Aads>
<interw>2</interw> <interw>2</interw>
@@ -1234,12 +1005,6 @@
<uSurpInc>2</uSurpInc> <uSurpInc>2</uSurpInc>
<useXO>2</useXO> <useXO>2</useXO>
<ClangAsOpt>1</ClangAsOpt> <ClangAsOpt>1</ClangAsOpt>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Aads> </Aads>
</GroupArmAds> </GroupArmAds>
</GroupOption> </GroupOption>
@@ -1271,8 +1036,6 @@
<AssembleAssemblyFile>2</AssembleAssemblyFile> <AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly> <PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode> <StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg> <ComprImg>1</ComprImg>
</CommonProperty> </CommonProperty>
<GroupArmAds> <GroupArmAds>
@@ -1300,12 +1063,6 @@
<v6Lto>2</v6Lto> <v6Lto>2</v6Lto>
<v6WtE>2</v6WtE> <v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti> <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads> </Cads>
<Aads> <Aads>
<interw>2</interw> <interw>2</interw>
@@ -1318,12 +1075,6 @@
<uSurpInc>2</uSurpInc> <uSurpInc>2</uSurpInc>
<useXO>2</useXO> <useXO>2</useXO>
<ClangAsOpt>1</ClangAsOpt> <ClangAsOpt>1</ClangAsOpt>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Aads> </Aads>
</GroupArmAds> </GroupArmAds>
</GroupOption> </GroupOption>
@@ -1764,20 +1515,18 @@
</Groups> </Groups>
</Target> </Target>
</Targets> </Targets>
<RTE> <RTE>
<apis/> <apis />
<components> <components>
<component Cclass="CMSIS" Cgroup="CORE" Cvendor="ARM" Cversion="4.3.0" condition="CMSIS Core"> <component Cclass="CMSIS" Cgroup="CORE" Cvendor="ARM" Cversion="4.3.0" condition="CMSIS Core">
<package name="CMSIS" schemaVersion="1.3" url="http://www.keil.com/pack/" vendor="ARM" version="4.5.0"/> <package name="CMSIS" schemaVersion="1.3" url="http://www.keil.com/pack/" vendor="ARM" version="4.5.0" />
<targetInfos> <targetInfos>
<targetInfo name="IPort"/> <targetInfo name="IPort" />
</targetInfos> </targetInfos>
</component> </component>
</components> </components>
<files/> <files />
</RTE> </RTE>
<LayerInfo> <LayerInfo>
<Layers> <Layers>
<Layer> <Layer>
@@ -1786,5 +1535,5 @@
</Layer> </Layer>
</Layers> </Layers>
</LayerInfo> </LayerInfo>
</Project> </Project>

View File

@@ -29,7 +29,7 @@
; <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> ; <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h> ; </h>
Stack_Size EQU 0x2048 Stack_Size EQU 0x1000
AREA STACK, NOINIT, READWRITE, ALIGN=3 AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size Stack_Mem SPACE Stack_Size
@@ -40,7 +40,7 @@ __initial_sp
; <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> ; <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h> ; </h>
Heap_Size EQU 0x20000 Heap_Size EQU 0x2000
AREA HEAP, NOINIT, READWRITE, ALIGN=3 AREA HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base __heap_base

View File

@@ -19,14 +19,13 @@ void charger_to_server_0X01(uint8_t stake_index)
load_charger_serial(stake_index,data.charger_serial); // 加载充电桩序列号 load_charger_serial(stake_index,data.charger_serial); // 加载充电桩序列号
data.charger_type = CHARGER_TYPE_DC; data.charger_type = CHARGER_TYPE_DC;
data.gun_num = GUN_NUM; data.gun_num = GUN_NUM;
data.protocol_ver = g_charger_manager.charger_piles[0].login_info.software_ver; data.protocol_ver = g_charger_manager.charger_piles[stake_index - 1].login_info.protocol_ver;
memcpy(data.software_ver, SOFTWARE_VERSION, strlen(SOFTWARE_VERSION)); memcpy(data.software_ver, SOFTWARE_VERSION, strlen(SOFTWARE_VERSION));
data.net_conn_type = NET_CONN_TYPE; data.net_conn_type = NET_CONN_TYPE;
data.tele_factory = TELE_FACTORY; data.tele_factory = TELE_FACTORY;
memcpy(data.sim, iccid_ascii, strlen(iccid_ascii)); memcpy(data.sim, iccid_ascii, strlen(iccid_ascii));
printf("Frame Type:0x01 充电桩登录认证(桩->平台)"); printf("北向:对电桩 %d 发送登录认证,序列号:%s\r\n", stake_index,data.charger_serial);
pack_and_send_server_data(FRAME_TYPE_0X01, 0, pack_serial, (uint8_t *)&data, sizeof(PACK_DATA_0X01),stake_index); pack_and_send_server_data(FRAME_TYPE_0X01, stake_index, 0, (uint8_t *)&data, sizeof(PACK_DATA_0X01),stake_index);
pack_serial++;
} }
@@ -37,9 +36,8 @@ void charger_to_server_0X03(uint8_t stake_index,uint8_t gun_index, uint8_t gun_s
load_charger_serial(stake_index,data.charger_serial); // 加载充电桩序列号 load_charger_serial(stake_index,data.charger_serial); // 加载充电桩序列号
data.gun_index = gun_index; data.gun_index = gun_index;
data.gun_status = gun_status; data.gun_status = gun_status;
printf("Frame Type:0x03 充电桩心跳包(桩->平台)"); printf("北向:对电桩 %d 发送心跳请求,枪号:%d状态%d\r\n", stake_index,gun_index,gun_status);
pack_and_send_server_data(FRAME_TYPE_0X03, 0, pack_serial, (uint8_t *)&data, sizeof(PACK_DATA_0X03),stake_index); pack_and_send_server_data(FRAME_TYPE_0X03, stake_index, 0, (uint8_t *)&data, sizeof(PACK_DATA_0X03),stake_index);
pack_serial++;
} }
// 计费模型验证请求 // 计费模型验证请求
@@ -49,9 +47,8 @@ void charger_to_server_0X05(uint16_t num,uint8_t stake_index)
load_charger_serial(stake_index,data.charger_serial); // 加载充电桩序列号 load_charger_serial(stake_index,data.charger_serial); // 加载充电桩序列号
data.fee_model_no = num; data.fee_model_no = num;
printf("Frame Type:0x05 计费模型验证请求(桩->平台)"); printf("北向:对电桩 %d 计费模型验证请求,模型号:%d\r\n", stake_index,num);
pack_and_send_server_data(FRAME_TYPE_0X05, 0, pack_serial, (uint8_t *)&data, sizeof(PACK_DATA_0X05),stake_index); pack_and_send_server_data(FRAME_TYPE_0X05, stake_index, 0, (uint8_t *)&data, sizeof(PACK_DATA_0X05),stake_index);
pack_serial++;
} }
// 充电桩计费模型请求 // 充电桩计费模型请求
@@ -60,25 +57,22 @@ void charger_to_server_0X09(uint8_t stake_index)
PACK_DATA_0X09 data = {0}; PACK_DATA_0X09 data = {0};
load_charger_serial(stake_index,data.charger_serial); // 加载充电桩序列号 load_charger_serial(stake_index,data.charger_serial); // 加载充电桩序列号
printf("Frame Type:0x09 充电桩计费模型请求(桩->平台)"); printf("北向:对电桩 %d 计费模型请求,序列号:%s\r\n", stake_index,data.charger_serial);
pack_and_send_server_data(FRAME_TYPE_0X09, 0, pack_serial, (uint8_t *)&data, sizeof(PACK_DATA_0X09),stake_index); pack_and_send_server_data(FRAME_TYPE_0X09, stake_index, 0, (uint8_t *)&data, sizeof(PACK_DATA_0X09),stake_index);
pack_serial++;
} }
// 上传实时监测数据 // 上传实时监测数据
void charger_to_server_0X13(uint8_t stake_index,uint8_t gun_index) void charger_to_server_0X13(uint8_t stake_index,uint8_t gun_index)
{ {
PACK_DATA_0X13 data = {0};
load_charger_serial(stake_index,data.charger_serial); // 加载充电桩序列号
// 加载充电桩交易序列号
const unsigned char trade_data[] = { const unsigned char trade_data[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00 0x00
}; };
PACK_DATA_0X13 data = {0};
load_charger_serial(stake_index,data.charger_serial); // 加载充电桩序列号
data.gun_index = gun_index; data.gun_index = gun_index;
//data.gun_back = getGunBack(All_status[gun_index-1]); //data.gun_back = getGunBack(All_status[gun_index-1]);
// data.gun_is_insert = getGunIsInsert(All_status[gun_index-1]); // data.gun_is_insert = getGunIsInsert(All_status[gun_index-1]);
@@ -99,9 +93,8 @@ void charger_to_server_0X13(uint8_t stake_index,uint8_t gun_index)
data.hard_fault = 0; data.hard_fault = 0;
} }
printf("Frame Type:0x13 上传实时监测数据(桩->平台)"); printf("北向:对电桩 %d 上传实时监测数据,枪号:%d状态%d返回%d是否插入%d\r\n", stake_index,gun_index,data.status,data.gun_back,data.gun_is_insert);
pack_and_send_server_data(FRAME_TYPE_0X13, 1, pack_serial, (uint8_t *)&data, sizeof(PACK_DATA_0X13),stake_index); pack_and_send_server_data(FRAME_TYPE_0X13, stake_index, 0, (uint8_t *)&data, sizeof(PACK_DATA_0X13),stake_index);
pack_serial++;
} }
@@ -115,9 +108,8 @@ void charger_to_server_0X33(uint8_t stake_mark,uint8_t gun_index,uint8_t result,
data.result = result; data.result = result;
data.err_code = err_code; data.err_code = err_code;
printf("Frame Type:0x33 平台启动回复(桩->平台)"); printf("北向:对电桩 %d 的平台启动回复,结果:%d错误码%d\r\n", stake_mark,result,err_code);
pack_and_send_server_data(FRAME_TYPE_0X33,0,pack_serial,(uint8_t *)&data,sizeof(PACK_DATA_0X33),stake_mark); pack_and_send_server_data(FRAME_TYPE_0X33, stake_mark, 0, (uint8_t *)&data, sizeof(PACK_DATA_0X33), stake_mark);
pack_serial++;
} }
#endif #endif

View File

@@ -214,6 +214,7 @@ void pack_and_send_server_data(uint8_t type, uint8_t encrypt, uint16_t serial, u
{ {
uint8_t index = 0; uint8_t index = 0;
uint16_t crc = 0; uint16_t crc = 0;
uint16_t current_serial = 0;
uint8_t *buf = NULL; uint8_t *buf = NULL;
buf = (uint8_t *)pvPortMalloc(len + 14); buf = (uint8_t *)pvPortMalloc(len + 14);
if (!buf) if (!buf)
@@ -221,6 +222,12 @@ void pack_and_send_server_data(uint8_t type, uint8_t encrypt, uint16_t serial, u
return; return;
} }
/* 原子获取全局包序号,避免多任务竞争 */
taskENTER_CRITICAL();
current_serial = pack_serial;
pack_serial++;
taskEXIT_CRITICAL();
buf[index++] = 0x55; buf[index++] = 0x55;
buf[index++] = 0xAA; buf[index++] = 0xAA;
buf[index++] = 0x01; buf[index++] = 0x01;
@@ -228,8 +235,8 @@ void pack_and_send_server_data(uint8_t type, uint8_t encrypt, uint16_t serial, u
buf[index++] = SERVER_PACK_START_FLAG; buf[index++] = SERVER_PACK_START_FLAG;
buf[index++] = len + 4; buf[index++] = len + 4;
buf[index++] = (serial >> 8) & 0xFF; buf[index++] = (current_serial >> 8) & 0xFF;
buf[index++] = serial & 0xFF; buf[index++] = current_serial & 0xFF;
buf[index++] = encrypt; buf[index++] = encrypt;
buf[index++] = type; buf[index++] = type;
@@ -244,10 +251,10 @@ void pack_and_send_server_data(uint8_t type, uint8_t encrypt, uint16_t serial, u
buf[index++] = 0xAA; buf[index++] = 0xAA;
buf[index++] = 0x55; buf[index++] = 0x55;
for (int i = 4; i < index - 2; i++) // for (int i = 4; i < index - 2; i++)
{ // {
printf("%02X", buf[i]); // printf("%02X", buf[i]);
} // }
Air724_Message_Send(buf, index); Air724_Message_Send(buf, index);
vPortFree(buf); vPortFree(buf);
} }
@@ -257,7 +264,8 @@ int get_num_from_string(const char *str, int *num)
int index = 0; int index = 0;
int t = 0; int t = 0;
int flag = 0; int flag = 0;
for (int i = 0; i < len; i++) int i;
for (i = 0; i < len; i++)
{ {
flag = 0; flag = 0;
while ((str[i] >= '0' && str[i] <= '9') && (i < len)) while ((str[i] >= '0' && str[i] <= '9') && (i < len))

View File

@@ -12,7 +12,7 @@ void on_cmd_frame_type_0X02(uint8_t stake_index, SERVER_PACK *pack)
{ {
g_charger_manager.charger_piles[stake_index - 1].is_online = 1; g_charger_manager.charger_piles[stake_index - 1].is_online = 1;
#ifdef DEBUG #ifdef DEBUG
printf("桩ID %d 登陆成功!\r\n", stake_index); printf("北向:桩ID %d 登陆成功!\r\n", stake_index);
#endif #endif
} }
} }
@@ -24,7 +24,7 @@ void on_cmd_frame_type_0X04(uint8_t stake_index, SERVER_PACK *pack)
PACK_DATA_0X04 data; PACK_DATA_0X04 data;
memcpy(&data, pack->data, sizeof(PACK_DATA_0X04)); memcpy(&data, pack->data, sizeof(PACK_DATA_0X04));
#ifdef DEBUG #ifdef DEBUG
printf("桩ID %d 收到心跳应答!\r\n", stake_index); printf("北向:桩ID %d 收到心跳应答!\r\n", stake_index);
#endif #endif
} }
@@ -36,7 +36,7 @@ void on_cmd_frame_type_0X06(uint8_t stake_index, SERVER_PACK *pack)
if (is_my_charger_serial(stake_index, data.charger_serial)) if (is_my_charger_serial(stake_index, data.charger_serial))
{ {
#ifdef DEBUG #ifdef DEBUG
printf("接收到计费模型验证应答模型ID%d, 验证结果:%d\r\n", data.fee_model_no, data.result); printf("北向:接收到计费模型验证应答模型ID%d, 验证结果:%d\r\n", data.fee_model_no, data.result);
#endif #endif
} }
} }
@@ -54,12 +54,12 @@ void on_cmd_frame_type_0X0A(uint8_t stake_index, SERVER_PACK *pack)
#ifdef DEBUG #ifdef DEBUG
printf("接收到计费模型应答,模型ID:%d\r\n", g_charger_manager.fee_model_global.fee_model_no); printf("北向:接收到计费模型应答,模型ID:%d\r\n", g_charger_manager.fee_model_global.fee_model_no);
printf("尖电费率:%d 服务费:%d\r\n", g_charger_manager.fee_model_global.shark_fee_ratio, g_charger_manager.fee_model_global.shark_service_ratio); printf("尖电费率:%d 服务费:%d\r\n", g_charger_manager.fee_model_global.shark_fee_ratio, g_charger_manager.fee_model_global.shark_service_ratio);
printf("峰电费率:%d 服务费:%d\r\n", g_charger_manager.fee_model_global.peak_fee_ratio, g_charger_manager.fee_model_global.peak_service_ratio); printf("峰电费率:%d 服务费:%d\r\n", g_charger_manager.fee_model_global.peak_fee_ratio, g_charger_manager.fee_model_global.peak_service_ratio);
printf("平电费率:%d 服务费:%d\r\n", g_charger_manager.fee_model_global.flat_fee_ratio, g_charger_manager.fee_model_global.flat_service_ratio); printf("平电费率:%d 服务费:%d\r\n", g_charger_manager.fee_model_global.flat_fee_ratio, g_charger_manager.fee_model_global.flat_service_ratio);
printf("谷电费率:%d 服务费:%d\r\n", g_charger_manager.fee_model_global.valley_fee_ratio, g_charger_manager.fee_model_global.valley_service_ratio); printf("谷电费率:%d 服务费:%d\r\n", g_charger_manager.fee_model_global.valley_fee_ratio, g_charger_manager.fee_model_global.valley_service_ratio);
printf("计损比例:%d%%\r\n", g_charger_manager.fee_model_global.loss_ratio); printf("计损比例: %d%% \r\n", g_charger_manager.fee_model_global.loss_ratio);
printf("\n合并后的费率时间段:\r\n"); printf("\n合并后的费率时间段:\r\n");
printf("================================================================\r\n"); printf("================================================================\r\n");
@@ -111,7 +111,7 @@ void on_cmd_frame_type_0X0A(uint8_t stake_index, SERVER_PACK *pack)
end_hour = 0; end_hour = 0;
} }
printf("%02d:%02d-%02d:%02d 为 %s费率\r", printf("%02d:%02d-%02d:%02d 为 %s 费率\r\n",
start_hour, start_min, start_hour, start_min,
end_hour, end_min, end_hour, end_min,
fee_name); fee_name);
@@ -137,21 +137,12 @@ void on_cmd_frame_type_0X58(uint8_t stake_index, SERVER_PACK *pack)
#ifdef DEBUG #ifdef DEBUG
char str[150]; char str[150];
Rs485_Message_Send("t0.txt=\"\"\xff\xff\xff", 12); Rs485_Message_Send("t0.txt=\"\"\xff\xff\xff", 12);
printf("接收到计费模型应答,模型ID:%d\r\n", g_charger_manager.fee_model_global.fee_model_no); printf("北向:接收到计费模型应答,模型ID:%d\r\n", g_charger_manager.fee_model_global.fee_model_no);
printf("尖电费率:%d 服务费:%d\r\n", g_charger_manager.fee_model_global.shark_fee_ratio, g_charger_manager.fee_model_global.shark_service_ratio); printf("尖电费率:%d 服务费:%d\r\n", g_charger_manager.fee_model_global.shark_fee_ratio, g_charger_manager.fee_model_global.shark_service_ratio);
printf("峰电费率:%d 服务费:%d\r\n", g_charger_manager.fee_model_global.peak_fee_ratio, g_charger_manager.fee_model_global.peak_service_ratio); printf("峰电费率:%d 服务费:%d\r\n", g_charger_manager.fee_model_global.peak_fee_ratio, g_charger_manager.fee_model_global.peak_service_ratio);
printf("平电费率:%d 服务费:%d\r\n", g_charger_manager.fee_model_global.flat_fee_ratio, g_charger_manager.fee_model_global.flat_service_ratio); printf("平电费率:%d 服务费:%d\r\n", g_charger_manager.fee_model_global.flat_fee_ratio, g_charger_manager.fee_model_global.flat_service_ratio);
printf("谷电费率:%d 服务费:%d\r\n", g_charger_manager.fee_model_global.valley_fee_ratio, g_charger_manager.fee_model_global.valley_service_ratio); printf("谷电费率:%d 服务费:%d\r\n", g_charger_manager.fee_model_global.valley_fee_ratio, g_charger_manager.fee_model_global.valley_service_ratio);
printf("计损比例:%d%%\r\n", g_charger_manager.fee_model_global.loss_ratio); printf("计损比例: %d%% \r\n", g_charger_manager.fee_model_global.loss_ratio);
sprintf(str, "t0.txt+=\"尖电费 %d 服务费 %d \r\n峰电费 %d 服务费 %d \r\n平电费 %d 服务费 %d \r\n谷电费 %d 服务费 %d \r\n计损比例 %d%%\r\n\"\xff\xff\xff",
g_charger_manager.fee_model_global.shark_fee_ratio, g_charger_manager.fee_model_global.shark_service_ratio,
g_charger_manager.fee_model_global.peak_fee_ratio, g_charger_manager.fee_model_global.peak_service_ratio,
g_charger_manager.fee_model_global.flat_fee_ratio, g_charger_manager.fee_model_global.flat_service_ratio,
g_charger_manager.fee_model_global.valley_fee_ratio, g_charger_manager.fee_model_global.valley_service_ratio,
g_charger_manager.fee_model_global.loss_ratio);
Rs485_Message_Send(str, strlen(str));
printf("\n合并后的费率时间段:\r\n"); printf("\n合并后的费率时间段:\r\n");
printf("================================================================\r\n"); printf("================================================================\r\n");
@@ -202,17 +193,10 @@ void on_cmd_frame_type_0X58(uint8_t stake_index, SERVER_PACK *pack)
end_hour = 0; end_hour = 0;
} }
printf("%02d:%02d-%02d:%02d 为 %s费率\r", printf("%02d:%02d-%02d:%02d 为 %s 费率\r",
start_hour, start_min, start_hour, start_min,
end_hour, end_min, end_hour, end_min,
fee_name); fee_name);
sprintf(str, "t0.txt+=\"%02d:%02d-%02d:%02d 为 %s费率 \r\n\"\xff\xff\xff",
start_hour, start_min,
end_hour, end_min,
fee_name);
Rs485_Message_Send(str, strlen(str));
i = j; // 跳到下一个不同费率段 i = j; // 跳到下一个不同费率段
} }
printf("================================================================\r\n"); printf("================================================================\r\n");
@@ -227,8 +211,9 @@ void on_cmd_frame_type_0X34(uint8_t stake_index, SERVER_PACK *pack)
uint8_t result = 1; uint8_t result = 1;
uint8_t err_code = 0; uint8_t err_code = 0;
memcpy(&data, pack->data, sizeof(PACK_DATA_0X34)); memcpy(&data, pack->data, sizeof(PACK_DATA_0X34));
set_trade_serial(data.gun_index, data.trade_serial, stake_index); set_trade_serial(stake_index,data.gun_index, data.trade_serial);
printf("北向:平台控制充电,桩ID:%d, 枪ID:%d, 金额:%d\r\n", stake_index, data.gun_index, data.remain_money);
if (!is_my_charger_serial(stake_index, data.charger_serial)) if (!is_my_charger_serial(stake_index, data.charger_serial))
{ {
result = 0; result = 0;
@@ -257,6 +242,7 @@ void on_cmd_frame_type_0X34(uint8_t stake_index, SERVER_PACK *pack)
// set_charge_start_mode(data.gun_index - 1, CAHRGE_START_MODE_APP); // set_charge_start_mode(data.gun_index - 1, CAHRGE_START_MODE_APP);
// update_remain_money_to_gun(data.gun_index - 1, data.remain_money); // update_remain_money_to_gun(data.gun_index - 1, data.remain_money);
// } // }
charger_to_server_0X33(stake_index, data.gun_index, result, err_code); charger_to_server_0X33(stake_index, data.gun_index, result, err_code);
} }
#if 0 #if 0

View File

@@ -9,11 +9,34 @@
*/ */
/* Includes -------------------------------------------------------------------*/ /* Includes -------------------------------------------------------------------*/
#include "drv_init.h" #include "drv_init.h"
// crc16_modbus.c
#include <stdint.h> #include <stdint.h>
/* code -----------------------------------------------------------------------*/ /* code -----------------------------------------------------------------------*/
void send_cmd_to_air724(uint8_t *cmd, uint16_t len)
{
Air724_Message_Send(cmd, len);
}
void send_server_address_to_air724(void)
{
char ip[] = YKC_SERVER_IP;
char port[6];
sprintf(port, "%d", YKC_SERVER_PORT);
uint8_t len = strlen(ip) + 1 + strlen(port);
uint8_t config_cmd[256] = {0x55, 0xAA, 0x04, 0x00, len};
uint8_t pos = 5;
memcpy(&config_cmd[pos], ip, strlen(ip));
pos += strlen(ip);
config_cmd[pos++] = 0x00;
memcpy(&config_cmd[pos], port, strlen(port));
pos += strlen(port);
config_cmd[pos++] = 0xAA;
config_cmd[pos++] = 0x55;
send_cmd_to_air724(config_cmd, pos);
pos = 0;
memset(config_cmd, 0, sizeof(config_cmd));
}
/** /**
* @brief drv_all_Init所有传感器、外设芯片、外部设备初始化 * @brief drv_all_Init所有传感器、外设芯片、外部设备初始化
* *
@@ -26,5 +49,5 @@
void drv_all_Init(void) void drv_all_Init(void)
{ {
AIR724_RESET(); /* AIR724 复位 */ AIR724_RESET(); /* AIR724 复位 */
} }

View File

@@ -10,6 +10,5 @@
/* Exported functions prototypes ------------------------------------------------------------------------*/ /* Exported functions prototypes ------------------------------------------------------------------------*/
void drv_all_Init(void); void drv_all_Init(void);
#endif /* __DRVINIT_H */ #endif /* __DRVINIT_H */

View File

@@ -12,7 +12,6 @@ const uint8_t piles_serial[6][7] = {
{0x88, 0x26, 0x01, 0x13, 0x12, 0x00, 0x03}, {0x88, 0x26, 0x01, 0x13, 0x12, 0x00, 0x03},
{0x88, 0x26, 0x01, 0x13, 0x12, 0x00, 0x04}, {0x88, 0x26, 0x01, 0x13, 0x12, 0x00, 0x04},
{0x88, 0x26, 0x01, 0x13, 0x12, 0x00, 0x05}, {0x88, 0x26, 0x01, 0x13, 0x12, 0x00, 0x05},
}; };
/** /**

View File

@@ -5,7 +5,7 @@
/* includes ----------------------------------------------------------------------------------------------*/ /* includes ----------------------------------------------------------------------------------------------*/
#include "global.h" #include "global.h"
#define MAX_CHARGER_COUNT 6 // 充电桩数量 #define MAX_CHARGER_COUNT 2 // 充电桩数量
#define MAX_GUN_PER_CHARGER 2 // 每个充电桩最多枪数 #define MAX_GUN_PER_CHARGER 2 // 每个充电桩最多枪数
/* 充电枪结构体*/ /* 充电枪结构体*/

View File

@@ -28,8 +28,6 @@
#include "usart.h" #include "usart.h"
#include "gpio.h" #include "gpio.h"
// #include "tim.h"
/* freeRTOS 相关 */ /* freeRTOS 相关 */
#include "cmsis_os.h" #include "cmsis_os.h"
#include "FreeRTOS.h" #include "FreeRTOS.h"
@@ -72,6 +70,9 @@
#define DEBUG 1 // 调试模式 #define DEBUG 1 // 调试模式
#define YKC_SERVER_IP "121.43.69.62" // YKC 服务器 IP 地址
#define YKC_SERVER_PORT 8767 // YKC 服务器端口号
/*- I/O 输出-*/ /*- I/O 输出-*/
#define AIR724_RESET() \ #define AIR724_RESET() \

View File

@@ -18,6 +18,8 @@ uint8_t uart1_tx_buffer[UART1_TX_BUFFER_SIZE];
uint8_t uart3_rx_buffer[UART3_RX_BUFFER_SIZE]; uint8_t uart3_rx_buffer[UART3_RX_BUFFER_SIZE];
uint8_t uart3_tx_buffer[UART3_TX_BUFFER_SIZE]; uint8_t uart3_tx_buffer[UART3_TX_BUFFER_SIZE];
static SemaphoreHandle_t air724_tx_mutex = NULL;
/* code -----------------------------------------------------------------------*/ /* code -----------------------------------------------------------------------*/
/** /**
* @brief fputcprintf映射 * @brief fputcprintf映射
@@ -46,7 +48,18 @@ int fputc(int ch, FILE *f)
*/ */
void Air724_Message_Send(uint8_t *data, uint16_t len) void Air724_Message_Send(uint8_t *data, uint16_t len)
{ {
HAL_UART_Transmit(&huart1, data, len, HAL_MAX_DELAY); if (air724_tx_mutex != NULL)
{
if (xSemaphoreTake(air724_tx_mutex, portMAX_DELAY) == pdTRUE)
{
HAL_UART_Transmit(&huart1, data, len, HAL_MAX_DELAY);
xSemaphoreGive(air724_tx_mutex);
}
}
else
{
HAL_UART_Transmit(&huart1, data, len, HAL_MAX_DELAY);
}
} }
void Rs485_Message_Send(uint8_t *data, uint16_t len) void Rs485_Message_Send(uint8_t *data, uint16_t len)
@@ -68,6 +81,7 @@ void Rs485_Message_Send(uint8_t *data, uint16_t len)
void hal_usart_Init(void) void hal_usart_Init(void)
{ {
air724_tx_mutex = xSemaphoreCreateMutex();
/* 初始化串口1 */ /* 初始化串口1 */
Air724_Message_Queue_Init(); // 初始化4G数据接收队列 Air724_Message_Queue_Init(); // 初始化4G数据接收队列

View File

@@ -89,7 +89,7 @@ void UDP_ParseTask_Function(void const *argument)
} }
else else
{ {
printf("Missing 'code' field\r\n"); printf("Missing 'code' field from \r\n");
cJSON_Delete(root); cJSON_Delete(root);
} }
vPortFree(msg.data); vPortFree(msg.data);
@@ -145,9 +145,10 @@ void UDPTask_Function(void const *argument)
{ {
memcpy(msg.data, playload, playload_len); memcpy(msg.data, playload, playload_len);
msg.data[playload_len] = '\0'; msg.data[playload_len] = '\0';
// 队列满,释放数据内存
if (xQueueSend(UDP_Message_Queue, &msg, 0) != pdPASS) if (xQueueSend(UDP_Message_Queue, &msg, 0) != pdPASS)
{ {
vPortFree(msg.data); vPortFree(msg.data);
} }
} }
} }
@@ -178,6 +179,70 @@ void local_on_cmd_callback_power_on(uint8_t stake_index, cJSON *json_pack)
g_charger_manager.charger_piles[stake_index - 1].is_udp_online = true; // 设置桩为本地在线状态 g_charger_manager.charger_piles[stake_index - 1].is_udp_online = true; // 设置桩为本地在线状态
cJSON *root = NULL; cJSON *root = NULL;
uint8_t *str = NULL;
root = cJSON_CreateObject();
if (root == NULL)
{
printf("Failed to create JSON object for stake %d\r\n", stake_index);
return;
}
/* 添加一条字符串类型的JSON数据(添加一个链表节点) */
cJSON_AddNumberToObject(root, "id", stake_index);
cJSON_AddStringToObject(root, "cmd", "online");
cJSON_AddStringToObject(root, "type", "response");
str = cJSON_Print(root);
udp_send_response(stake_index, str, strlen(str));
free(str);
cJSON_Delete(root);
printf("南向:对电桩 %d 上电回复成功\r\n", stake_index);
}
/**
* @brief 解析充电桩心跳指令
* @note 回复心跳应答
* @param stake_index 桩索引
* @param json_pack json数据包
*/
void local_on_cmd_callback_heartbeat_response(uint8_t stake_index, cJSON *json_pack)
{
if (stake_index > 6)
{
return;
}
//心跳unpack
cJSON *gun_array = cJSON_GetObjectItem(json_pack, "gun");
// 直接判断 type 字段
if (gun_array == NULL || gun_array->type != cJSON_Array)
{
printf(" └── [error] 缺少 gun 数组\r\n");
return;
}
int gun_count = cJSON_GetArraySize(gun_array);
for (int i = 0; i < gun_count; i++)
{
cJSON *gun = cJSON_GetArrayItem(gun_array, i);
if (!gun) continue;
cJSON *id = cJSON_GetObjectItem(gun, "id");
cJSON *state = cJSON_GetObjectItem(gun, "state");
if (!id || !state) continue;
// if (id->valueint == 1) pile->gun1_state = state->valueint;
// if (id->valueint == 2) pile->gun2_state = state->valueint;
printf(" └── [info] 桩%d 枪%d state=%d\r\n", stake_index, id->valueint, state->valueint);
}
//心跳回复组包
cJSON *root = NULL;
char *str = NULL; char *str = NULL;
root = cJSON_CreateObject(); root = cJSON_CreateObject();
@@ -189,29 +254,15 @@ void local_on_cmd_callback_power_on(uint8_t stake_index, cJSON *json_pack)
/* 添加一条字符串类型的JSON数据(添加一个链表节点) */ /* 添加一条字符串类型的JSON数据(添加一个链表节点) */
cJSON_AddNumberToObject(root, "id", stake_index); cJSON_AddNumberToObject(root, "id", stake_index);
cJSON_AddStringToObject(root, "cmd", "power_on"); cJSON_AddStringToObject(root, "cmd", "heartbeat");
cJSON_AddNumberToObject(root, "code", 1); cJSON_AddStringToObject(root, "type", "response");
str = cJSON_Print(root); str = cJSON_Print(root);
udp_send_response(stake_index, str, strlen(str)); udp_send_response(stake_index, str, strlen(str));
free(str); free(str);
cJSON_Delete(root); cJSON_Delete(root);
printf("电桩 %d 上电报文\r\n", stake_index); printf("南向:对电桩 %d 心跳回复成功\r\n", stake_index);
}
/**
* @brief 解析充电桩计费模型请求指令
* @note 获取云快充下发的计费模型,回复给充电桩
* @param stake_index 桩索引
* @param json_pack json数据包
*/
void local_on_cmd_callback_get_billing_model(uint8_t stake_index, cJSON *json_pack)
{
if (stake_index > 6)
{
return;
}
} }
@@ -220,13 +271,17 @@ void handle_udp_downlink(uint8_t id, const char *cmd, cJSON *json_pack)
{ {
if (cmd == NULL) if (cmd == NULL)
return; return;
if (strcmp(cmd, "power_on") == 0) // 处理上电指令
if (strcmp(cmd, "online") == 0)
{ {
printf("南向:收到电桩 %d 上电指令\r\n", id);
local_on_cmd_callback_power_on(id, json_pack); local_on_cmd_callback_power_on(id, json_pack);
} }
else if (strcmp(cmd, "get_billing_model") == 0) // 处理心跳指令
else if (strcmp(cmd, "heartbeat") == 0)
{ {
local_on_cmd_callback_get_billing_model(id, json_pack); printf("南向:收到电桩 %d 心跳指令\r\n", id);
local_on_cmd_callback_heartbeat_response(id, json_pack);
} }
else else
{ {

View File

@@ -45,7 +45,6 @@ void DownLinkTask_Function(void const *argument)
while (1) while (1)
{ {
/*---------------------------------------------------获取任务运行状态---------------------------------------------------*/ /*---------------------------------------------------获取任务运行状态---------------------------------------------------*/
TaskRunTimeStat.DownLinkTask.threads_runtime = GetTask_RunTime(DownLinkTaskID); TaskRunTimeStat.DownLinkTask.threads_runtime = GetTask_RunTime(DownLinkTaskID);
TaskRunTimeStat.DownLinkTask.threads_counter = GetTask_Beatcnt(DownLinkTaskID); TaskRunTimeStat.DownLinkTask.threads_counter = GetTask_Beatcnt(DownLinkTaskID);
TaskRunTimeStat.DownLinkTask.threads_freestack = Get_Free_Stack(DownLinkTaskID); TaskRunTimeStat.DownLinkTask.threads_freestack = Get_Free_Stack(DownLinkTaskID);
@@ -74,22 +73,30 @@ void DownLinkTask_Function(void const *argument)
memcpy(frame.data, ykc_downlink_frame + HEADER_LENGTH, frame.len - 4); memcpy(frame.data, ykc_downlink_frame + HEADER_LENGTH, frame.len - 4);
frame.crc = (ykc_downlink_frame[HEADER_LENGTH + frame.len] << 8) | ykc_downlink_frame[HEADER_LENGTH + frame.len + 1]; frame.crc = (ykc_downlink_frame[HEADER_LENGTH + frame.len] << 8) | ykc_downlink_frame[HEADER_LENGTH + frame.len + 1];
printf("Raw Bytes: "); // printf("Raw Bytes: ");
for (int i = 0; i < ykc_downlink_frame_len; i++) // for (int i = 0; i < ykc_downlink_frame_len; i++)
{ // {
printf("%02X ", ykc_downlink_frame[i]); // printf("%02X ", ykc_downlink_frame[i]);
if ((i + 1) % 16 == 0) // 每16字节换行 // if ((i + 1) % 16 == 0) // 每16字节换行
{ // {
printf("\r"); // printf("\r");
} // }
} // }
printf("\r"); // printf("\r");
handle_ykc_downlink(charger_index, &frame); handle_ykc_downlink(charger_index, &frame);
vPortFree(frame.data); vPortFree(frame.data);
} }
break; break;
case 0x83:
{
if (air724_rx_msg[3] == 0x01)
printf("4GSocket %d 通道连接成功\r\n", air724_rx_msg[4]);
if (air724_rx_msg[3] == 0x02)
printf("4GSocket %d 通道断开成功\r\n", air724_rx_msg[4]);
}
break;
} }
} }
} }

View File

@@ -13,34 +13,6 @@
void HeartBeat_Sign(void); void HeartBeat_Sign(void);
/**
* @brief 发送显示数据
* @note 发送显示数据,包括充电桩的连接状态和工作状态
*/
void Send_Display_Data(void)
{
#ifdef DEBUG
char str[128];
sprintf(str, "t1.bco=%s\xff\xff\xfft2.bco=%s\xff\xff\xfft3.bco=%s\xff\xff\xfft4.bco=%s\xff\xff\xfft5.bco=%s\xff\xff\xfft6.bco=%s\xff\xff\xff",
g_charger_manager.charger_piles[0].is_udp_online ? "GREEN" : "RED",
g_charger_manager.charger_piles[1].is_udp_online ? "GREEN" : "RED",
g_charger_manager.charger_piles[2].is_udp_online ? "GREEN" : "RED",
g_charger_manager.charger_piles[3].is_udp_online ? "GREEN" : "RED",
g_charger_manager.charger_piles[4].is_udp_online ? "GREEN" : "RED",
g_charger_manager.charger_piles[5].is_udp_online ? "GREEN" : "RED");
Rs485_Message_Send(str, strlen(str));
sprintf(str, "t7.bco=%s\xff\xff\xfft8.bco=%s\xff\xff\xfft9.bco=%s\xff\xff\xfft10.bco=%s\xff\xff\xfft11.bco=%s\xff\xff\xfft12.bco=%s\xff\xff\xff",
g_charger_manager.charger_piles[0].is_online ? "GREEN" : "RED",
g_charger_manager.charger_piles[1].is_online ? "GREEN" : "RED",
g_charger_manager.charger_piles[2].is_online ? "GREEN" : "RED",
g_charger_manager.charger_piles[3].is_online ? "GREEN" : "RED",
g_charger_manager.charger_piles[4].is_online ? "GREEN" : "RED",
g_charger_manager.charger_piles[5].is_online ? "GREEN" : "RED");
Rs485_Message_Send(str, strlen(str));
#endif
}
/** /**
* @funNm : HeartbeatTask_Function * @funNm : HeartbeatTask_Function
@@ -69,13 +41,30 @@ void HeartbeatTask_Function(void const *argument)
* @param : none * @param : none
* @retval: void * @retval: void
*/ */
static uint32_t last_heartbeat_tick[MAX_CHARGER_COUNT] = {0};
void HeartBeat_Sign(void) void HeartBeat_Sign(void)
{ {
if (g_charger_manager.charger_piles[0].is_online) int i;
uint32_t now = HAL_GetTick();
bool any_online = false;
/* 6路桩独立心跳互不影响 */
for (i = 0; i < MAX_CHARGER_COUNT; i++)
{
if (g_charger_manager.charger_piles[i].is_online)
{
any_online = true;
if ((now - last_heartbeat_tick[i]) >= 8000)
{
last_heartbeat_tick[i] = now;
charger_to_server_0X03(i + 1, 1, 0);
}
}
}
if (any_online)
{ {
RUN_EVERY(8000, tick_A, {
charger_to_server_0X03(1, 1, 0);
});
RUN_EVERY(100, tick_B, { RUN_EVERY(100, tick_B, {
System_Mode_Led_Toggle(); System_Mode_Led_Toggle();
}); });
@@ -90,7 +79,4 @@ void HeartBeat_Sign(void)
RUN_EVERY(1000, tick_D, { RUN_EVERY(1000, tick_D, {
System_Run_Led_Toggle(); System_Run_Led_Toggle();
}); });
RUN_EVERY(500, tick_E, {
Send_Display_Data();
});
} }

View File

@@ -28,6 +28,8 @@ void YkcTask_Function(void const *argument)
{ {
init_chargers(); /* 初始化桩结构体*/ init_chargers(); /* 初始化桩结构体*/
ulTaskNotifyTake(pdTRUE, portMAX_DELAY); /* 等待桩通讯协议层完成*/ ulTaskNotifyTake(pdTRUE, portMAX_DELAY); /* 等待桩通讯协议层完成*/
osDelay(5000);
// send_server_address_to_air724();
while (1) while (1)
{ {
TaskRunTimeStat.YkcTask.threads_runtime = GetTask_RunTime(YkcTaskID); TaskRunTimeStat.YkcTask.threads_runtime = GetTask_RunTime(YkcTaskID);
@@ -36,36 +38,59 @@ void YkcTask_Function(void const *argument)
switch (SETP) switch (SETP)
{ {
case 0: case 0:
{
if (g_charger_manager.charger_piles[1 - 1].is_udp_online)
{
uint8_t open_cmd[] = { 0x55, 0xAA, 0x3, 0x01, 0x01, 0xAA, 0x55};
Air724_Message_Send(open_cmd, sizeof(open_cmd));
osDelay(3000);
SETP = 1;
}
else
{
printf("网关:等待桩上电指令\r\n");
osDelay(1000);
SETP = 0;
}
}
break;
case 1:
{ {
if (!g_charger_manager.charger_piles[1 - 1].is_online) if (!g_charger_manager.charger_piles[1 - 1].is_online)
{ {
charger_to_server_0X01(1); charger_to_server_0X01(1);
} }
else else
{ {
SETP = 1;
}
}
break;
case 1:
{
if (!g_charger_manager.charger_piles[1 - 1].get_model)
charger_to_server_0X09(1); // 桩1计费模型请求
else
SETP = 2; SETP = 2;
}
osDelay(5000);
} }
break; break;
case 2: case 2:
{
if (!g_charger_manager.charger_piles[1 - 1].get_model)
charger_to_server_0X09(1); // 桩1计费模型请求
else
SETP = 3;
osDelay(3000);
}
break;
case 3:
{ {
charger_to_server_0X13(1, 1); // 上传状态 charger_to_server_0X13(1, 1); // 上传状态
osDelay(15000);
} }
break; break;
default: default:
break; break;
} }
osDelay(2000); //osDelay(2000);
} }
} }