重构串口驱动输入输出引脚,便于移植
This commit is contained in:
parent
bf7743b3cc
commit
365bb2a26e
|
@ -12,7 +12,7 @@ Pwm::Pwm(TIMER index) : Timer(index)
|
|||
Enabled[i] = false;
|
||||
}
|
||||
|
||||
Remap = 0;
|
||||
//Remap = 0;
|
||||
}
|
||||
|
||||
Pwm::~Pwm()
|
||||
|
|
|
@ -12,7 +12,7 @@ public:
|
|||
ushort Pulse[4]; // 每个通道的占空比
|
||||
bool Polarity = true; // 极性。默认true高电平
|
||||
bool IdleState = true; // 空闲状态。
|
||||
uint Remap; // 重映射。0不映射,其它为实际映射数字
|
||||
//uint Remap; // 重映射。0不映射,其它为实际映射数字
|
||||
AlternatePort* Ports[4];
|
||||
byte Enabled[4]; // 每个通道是否启用
|
||||
|
||||
|
|
|
@ -26,9 +26,12 @@ void SerialPort::Init()
|
|||
RS485 = nullptr;
|
||||
Error = 0;
|
||||
|
||||
Remap = false;
|
||||
Remap = 0;
|
||||
MinSize = 1;
|
||||
|
||||
Pins[0] = Pins[1] = P0;
|
||||
Ports[0] = Ports[1] = nullptr;
|
||||
|
||||
_taskidRx = 0;
|
||||
|
||||
OnInit();
|
||||
|
|
|
@ -20,21 +20,17 @@ private:
|
|||
int _baudRate;
|
||||
|
||||
void* _port;
|
||||
AlternatePort _tx;
|
||||
#if defined(STM32F0) || defined(GD32F150) || defined(STM32F4)
|
||||
AlternatePort _rx;
|
||||
#else
|
||||
InputPort _rx;
|
||||
#endif
|
||||
|
||||
void Init();
|
||||
|
||||
public:
|
||||
char Name[5]; // 名称。COMxx,后面1字节\0表示结束
|
||||
bool Remap; // 是否重映射
|
||||
byte Remap; // 重映射组
|
||||
OutputPort* RS485; // RS485使能引脚
|
||||
int Error; // 错误计数
|
||||
int ByteTime; // 字节间隔,最小1ms
|
||||
Pin Pins[2]; // Tx/Rx
|
||||
Port* Ports[2]; // Tx/Rx
|
||||
|
||||
// 收发缓冲区
|
||||
Queue Tx;
|
||||
|
@ -55,14 +51,11 @@ public:
|
|||
|
||||
void SetBaudRate(int baudRate = SERIAL_BAUDRATE);
|
||||
|
||||
void GetPins(Pin* txPin, Pin* rxPin);
|
||||
|
||||
virtual void Register(TransportHandler handler, void* param = nullptr);
|
||||
|
||||
// 电源等级变更(如进入低功耗模式)时调用
|
||||
virtual void ChangePower(int level);
|
||||
|
||||
//virtual String ToString() const { return String(Name); }
|
||||
virtual String& ToStr(String& str) const { return str + Name; }
|
||||
|
||||
void OnTxHandler();
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
|
||||
const byte uart_irqs[] = UART_IRQs;
|
||||
|
||||
static void GetPins(byte index, byte remap, Pin* txPin, Pin* rxPin);
|
||||
|
||||
void SerialPort::OnInit()
|
||||
{
|
||||
_parity = USART_Parity_No;
|
||||
|
@ -22,6 +24,8 @@ bool SerialPort::OnSet()
|
|||
USART_TypeDef* const g_Uart_Ports[] = UARTS;
|
||||
assert_param(_index < ArrayLength(g_Uart_Ports));
|
||||
|
||||
GetPins(_index, Remap, &Pins[0], &Pins[1]);
|
||||
|
||||
auto sp = g_Uart_Ports[_index];
|
||||
_port = sp;
|
||||
|
||||
|
@ -32,8 +36,9 @@ bool SerialPort::OnSet()
|
|||
// 打开串口
|
||||
void SerialPort::OnOpen2()
|
||||
{
|
||||
Pin rx, tx;
|
||||
GetPins(&tx, &rx);
|
||||
// 串口引脚初始化
|
||||
if(!Ports[0]) Ports[0] = new Outport(Pins[0]);
|
||||
if(!Ports[1]) Ports[1] = new AlternatePort(Pins[1]);
|
||||
|
||||
//串口引脚初始化
|
||||
_tx.Set(tx).Open();
|
||||
|
@ -224,7 +229,7 @@ void SerialPort::OnHandler(ushort num, void* param)
|
|||
#pragma arm section code
|
||||
|
||||
// 获取引脚
|
||||
void SerialPort::GetPins(Pin* txPin, Pin* rxPin)
|
||||
void GetPins(byte index, byte remap, Pin* txPin, Pin* rxPin)
|
||||
{
|
||||
*rxPin = *txPin = P0;
|
||||
|
||||
|
@ -232,10 +237,10 @@ void SerialPort::GetPins(Pin* txPin, Pin* rxPin)
|
|||
const Pin* p = g_Uart_Pins;
|
||||
#ifdef STM32F1
|
||||
const Pin g_Uart_Pins_Map[] = UART_PINS_FULLREMAP;
|
||||
if(Remap) p = g_Uart_Pins_Map;
|
||||
if(remap) p = g_Uart_Pins_Map;
|
||||
#endif
|
||||
|
||||
int n = _index << 2;
|
||||
int n = index << 2;
|
||||
*txPin = p[n];
|
||||
*rxPin = p[n + 1];
|
||||
}
|
||||
|
|
|
@ -1,157 +0,0 @@
|
|||
#include "../stm32.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
unsigned int HSE_VALUE = 8000000;
|
||||
uint32_t SystemCoreClock = 72000000;
|
||||
__I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
|
||||
|
||||
void SystemInit(void)
|
||||
{
|
||||
HSE_VALUE = 8000000;
|
||||
SystemCoreClock = 72000000;
|
||||
|
||||
/* Configure the System clock frequency, AHB/APBx prescalers and Flash settings */
|
||||
SetSysClock(SystemCoreClock, HSE_VALUE);
|
||||
|
||||
SCB->VTOR = FLASH_BASE; // Vector Table Relocation in Internal FLASH
|
||||
}
|
||||
|
||||
void SetSysClock(unsigned int clock, unsigned int cystalClock)
|
||||
{
|
||||
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
|
||||
uint32_t mull, mull2;
|
||||
|
||||
/* Reset the RCC clock configuration to the default reset state(for debug purpose) */
|
||||
/* Set HSION bit */
|
||||
RCC->CR |= (uint32_t)0x00000001;
|
||||
|
||||
/* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
|
||||
#ifndef STM32F10X_CL
|
||||
RCC->CFGR &= (uint32_t)0xF8FF0000;
|
||||
#else
|
||||
RCC->CFGR &= (uint32_t)0xF0FF0000;
|
||||
#endif /* STM32F10X_CL */
|
||||
|
||||
/* Reset HSEON, CSSON and PLLON bits */
|
||||
RCC->CR &= (uint32_t)0xFEF6FFFF;
|
||||
|
||||
/* Reset HSEBYP bit */
|
||||
RCC->CR &= (uint32_t)0xFFFBFFFF;
|
||||
|
||||
/* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
|
||||
RCC->CFGR &= (uint32_t)0xFF80FFFF;
|
||||
|
||||
#ifdef STM32F10X_CL
|
||||
/* Reset PLL2ON and PLL3ON bits */
|
||||
RCC->CR &= (uint32_t)0xEBFFFFFF;
|
||||
|
||||
/* Disable all interrupts and clear pending bits */
|
||||
RCC->CIR = 0x00FF0000;
|
||||
|
||||
/* Reset CFGR2 register */
|
||||
RCC->CFGR2 = 0x00000000;
|
||||
#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
|
||||
/* Disable all interrupts and clear pending bits */
|
||||
RCC->CIR = 0x009F0000;
|
||||
|
||||
/* Reset CFGR2 register */
|
||||
RCC->CFGR2 = 0x00000000;
|
||||
#else
|
||||
/* Disable all interrupts and clear pending bits */
|
||||
RCC->CIR = 0x009F0000;
|
||||
#endif /* STM32F10X_CL */
|
||||
|
||||
#if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)
|
||||
#ifdef DATA_IN_ExtSRAM
|
||||
SystemInit_ExtMemCtl();
|
||||
#endif /* DATA_IN_ExtSRAM */
|
||||
#endif
|
||||
|
||||
/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/
|
||||
/* Enable HSE */
|
||||
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
|
||||
|
||||
/* Wait till HSE is ready and if Time out is reached exit */
|
||||
do
|
||||
{
|
||||
HSEStatus = RCC->CR & RCC_CR_HSERDY;
|
||||
StartUpCounter++;
|
||||
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
|
||||
|
||||
if ((RCC->CR & RCC_CR_HSERDY) != RESET)
|
||||
HSEStatus = (uint32_t)0x01;
|
||||
else
|
||||
HSEStatus = (uint32_t)0x00;
|
||||
|
||||
if (HSEStatus == (uint32_t)0x01)
|
||||
{
|
||||
/* Enable Prefetch Buffer */
|
||||
FLASH->ACR |= FLASH_ACR_PRFTBE;
|
||||
|
||||
/* Flash 2 wait state */
|
||||
FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
|
||||
FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;
|
||||
|
||||
|
||||
/* HCLK = SYSCLK */
|
||||
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
|
||||
|
||||
/* PCLK2 = HCLK */
|
||||
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
|
||||
|
||||
/* PCLK1 = HCLK */
|
||||
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
|
||||
|
||||
#ifdef STM32F10X_CL
|
||||
/* Configure PLLs ------------------------------------------------------*/
|
||||
/* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */
|
||||
/* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */
|
||||
|
||||
RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |
|
||||
RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
|
||||
RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |
|
||||
RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);
|
||||
|
||||
/* Enable PLL2 */
|
||||
RCC->CR |= RCC_CR_PLL2ON;
|
||||
/* Wait till PLL2 is ready */
|
||||
while((RCC->CR & RCC_CR_PLL2RDY) == 0) { }
|
||||
|
||||
/* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */
|
||||
RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
|
||||
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 |
|
||||
RCC_CFGR_PLLMULL9);
|
||||
#else
|
||||
/* PLL configuration: PLLCLK = HSE * 9 = 72 MHz */
|
||||
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
|
||||
RCC_CFGR_PLLMULL));
|
||||
//RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);
|
||||
// 支持超频,主频必须是8M的倍频
|
||||
mull = clock / cystalClock;
|
||||
mull2 = (mull - 2) << 18;
|
||||
// 处理0.5倍频
|
||||
if( (mull * cystalClock + cystalClock / 2) == clock )
|
||||
{
|
||||
mull = 2 * clock / cystalClock;
|
||||
mull2 = (mull - 2 ) << 18 | RCC_CFGR_PLLXTPRE_HSE_Div2;
|
||||
}
|
||||
|
||||
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | mull2);
|
||||
#endif /* STM32F10X_CL */
|
||||
|
||||
/* Enable PLL */
|
||||
RCC->CR |= RCC_CR_PLLON;
|
||||
|
||||
/* Wait till PLL is ready */
|
||||
while((RCC->CR & RCC_CR_PLLRDY) == 0) { }
|
||||
|
||||
/* Select PLL as system clock source */
|
||||
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
|
||||
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
|
||||
|
||||
/* Wait till PLL is used as system clock source */
|
||||
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08) { }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
var build = Builder.Create("GCCArm");
|
||||
build.Init();
|
||||
build.CPU = "Cortex-M3";
|
||||
build.Linux = true;
|
||||
build.RebuildTime = 7 * 24 * 3600;
|
||||
build.Defines.Add("RTL8710");
|
||||
build.AddIncludes("..\\..\\..\\GCCLib\\", true, true);
|
||||
build.AddIncludes("..\\..\\", false);
|
||||
build.AddFiles(".", "*.c;Sys.cpp;Interrupt.cpp;Time.cpp;Timer.cpp");
|
||||
//build.AddFiles("..\\CortexM", "*.c;*.cpp");
|
||||
build.Libs.Clear();
|
||||
build.CompileAll();
|
||||
build.BuildLib("..\\..\\libSmartOS_RTL8710.a");
|
||||
|
||||
build.Debug = true;
|
||||
//build.CompileAll();
|
||||
//build.BuildLib("..\\..\\libSmartOS_RTL8710.a");
|
|
@ -1,201 +0,0 @@
|
|||
#include "Device\Flash.h"
|
||||
|
||||
#include "RTL871x.h"
|
||||
|
||||
#define FLASH_DEBUG DEBUG
|
||||
|
||||
//static const uint STM32_FLASH_KEY1 = 0x45670123;
|
||||
//static const uint STM32_FLASH_KEY2 = 0xcdef89ab;
|
||||
|
||||
#if defined (STM32F10X_HD) || defined (STM32F10X_HD_VL) || defined (STM32F10X_CL) || defined (STM32F10X_XL)
|
||||
#define FLASH_PAGE_SIZE ((uint16_t)0x800)
|
||||
#else
|
||||
#define FLASH_PAGE_SIZE ((uint16_t)0x400)
|
||||
#endif
|
||||
|
||||
void Flash::OnInit()
|
||||
{
|
||||
Block = FLASH_PAGE_SIZE;
|
||||
}
|
||||
|
||||
/* 写入段数据 (起始段,段数量,目标缓冲区,读改写) */
|
||||
bool Flash::WriteBlock(uint address, const byte* buf, uint len, bool inc) const
|
||||
{
|
||||
if(address < Start || address + len > Start + Size) return false;
|
||||
|
||||
// 进行闪存编程操作时(写或擦除),必须打开内部的RC振荡器(HSI)
|
||||
// 打开 HSI 时钟
|
||||
RCC->CR |= RCC_CR_HSION;
|
||||
while(!(RCC->CR & RCC_CR_HSIRDY));
|
||||
|
||||
/*if (FLASH->CR & FLASH_CR_LOCK) { // unlock
|
||||
FLASH->KEYR = STM32_FLASH_KEY1;
|
||||
FLASH->KEYR = STM32_FLASH_KEY2;
|
||||
}*/
|
||||
FLASH_Unlock();
|
||||
|
||||
ushort* s = (ushort*)address;
|
||||
ushort* e = (ushort*)(address + len);
|
||||
const ushort* p = (const ushort*)buf;
|
||||
|
||||
// 开始编程
|
||||
FLASH->CR = FLASH_CR_PG;
|
||||
//FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);
|
||||
|
||||
while(s < e) {
|
||||
if (*s != *p) {
|
||||
*s = *p;
|
||||
while (FLASH->SR & FLASH_SR_BSY);
|
||||
if (*s != *p) {
|
||||
debug_printf("Flash::WriteBlock 失败 0x%08x, 写 0x%04x, 读 0x%04x\r\n", s, *p, *s);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
s++;
|
||||
if(inc) p++;
|
||||
}
|
||||
|
||||
// 重置并锁定控制器。直接赋值一了百了,后面两个都是位运算,更麻烦
|
||||
//FLASH->CR = FLASH_CR_LOCK;
|
||||
//FLASH->CR &= ~FLASH_CR_PG;
|
||||
FLASH_Lock();
|
||||
|
||||
// 关闭 HSI 时钟
|
||||
RCC->CR &= ~RCC_CR_HSION;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* 擦除块 (段地址) */
|
||||
bool Flash::EraseBlock(uint address) const
|
||||
{
|
||||
if(address < Start || address + Block > Start + Size) return false;
|
||||
|
||||
#if FLASH_DEBUG
|
||||
debug_printf("\tFlash::EraseBlock(0x%08x)\r\n", address);
|
||||
#endif
|
||||
|
||||
// 进行闪存编程操作时(写或擦除),必须打开内部的RC振荡器(HSI)
|
||||
// 打开 HSI 时钟
|
||||
RCC->CR |= RCC_CR_HSION;
|
||||
while(!(RCC->CR & RCC_CR_HSIRDY));
|
||||
|
||||
/*if (FLASH->CR & FLASH_CR_LOCK) { // unlock
|
||||
FLASH->KEYR = STM32_FLASH_KEY1;
|
||||
FLASH->KEYR = STM32_FLASH_KEY2;
|
||||
}*/
|
||||
FLASH_Unlock();
|
||||
|
||||
// 打开擦除
|
||||
/*FLASH->CR = FLASH_CR_PER;
|
||||
// 设置页地址
|
||||
FLASH->AR = (uint)address;
|
||||
// 开始擦除
|
||||
FLASH->CR = FLASH_CR_PER | FLASH_CR_STRT;
|
||||
// 确保繁忙标记位被设置 (参考 STM32 勘误表)
|
||||
FLASH->CR = FLASH_CR_PER | FLASH_CR_STRT;
|
||||
// 等待完成
|
||||
while (FLASH->SR & FLASH_SR_BSY);*/
|
||||
|
||||
//FLASH_Status status = FLASH_COMPLETE;
|
||||
//boolret = true;
|
||||
|
||||
#ifndef STM32F4
|
||||
FLASH_Status status = FLASH_ErasePage(address);
|
||||
#else
|
||||
FLASH_Status status = FLASH_EraseSector(address, VoltageRange_3);
|
||||
#endif
|
||||
bool ret = status == FLASH_COMPLETE;
|
||||
|
||||
// 重置并锁定控制器。直接赋值一了百了,后面两个都是位运算,更麻烦
|
||||
//FLASH->CR = FLASH_CR_LOCK;
|
||||
//FLASH->CR &= ~FLASH_CR_PER;
|
||||
FLASH_Lock();
|
||||
|
||||
// 关闭 HSI 时钟
|
||||
RCC->CR &= ~RCC_CR_HSION;
|
||||
|
||||
#if FLASH_DEBUG
|
||||
/*byte* p = (byte*)address;
|
||||
for(int i=0; i<0x10; i++) debug_printf(" %02X", *p++);
|
||||
debug_printf("\r\n");*/
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
// 设置读保护
|
||||
if(FLASH_GetReadOutProtectionStatus() != SET)
|
||||
{
|
||||
FLASH_Unlock();
|
||||
FLASH_ReadOutProtection(ENABLE);
|
||||
}
|
||||
// 取消读保护 执行后Flash就清空了 注意:要上电复位才可以使用IC
|
||||
if(FLASH_GetReadOutProtectionStatus() != RESET)
|
||||
{
|
||||
FLASH_Unlock();
|
||||
FLASH_ReadOutProtection(DISABLE);
|
||||
|
||||
|
||||
|
||||
|
||||
* @arg OB_RDP_Level_0: No protection
|
||||
* @arg OB_RDP_Level_1: Read protection of the memory
|
||||
* @arg OB_RDP_Level_2: Chip protection
|
||||
* @retval FLASH Status: The returned value can be:
|
||||
* FLASH_ERROR_PROGRAM, FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
|
||||
|
||||
FLASH_Status FLASH_OB_RDPConfig(uint8_t OB_RDP)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}*/
|
||||
|
||||
|
||||
bool Flash::ReadOutProtection(bool set)
|
||||
{
|
||||
#if defined(STM32F1)
|
||||
bool isProt = FLASH_GetReadOutProtectionStatus() == SET ? true : false;
|
||||
if (isProt == set)return isProt;
|
||||
if (set)
|
||||
{
|
||||
// FLASH_Unlock(); // 多处资料都写了这一行并注释了
|
||||
FLASH_ReadOutProtection(ENABLE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 取消读保护会清空 Flash 内容,注意:要上电复位才可以使用IC
|
||||
FLASH_Unlock();
|
||||
FLASH_ReadOutProtection(DISABLE);
|
||||
}return set;
|
||||
#endif
|
||||
#if defined(STM32F0)
|
||||
bool isProt = FLASH_OB_GetRDP() == SET ? true : false;
|
||||
|
||||
if (isProt == set)return isProt;
|
||||
if (set)
|
||||
{
|
||||
FLASH_OB_Unlock();
|
||||
FLASH_OB_RDPConfig(OB_RDP_Level_1);
|
||||
// FLASH_OB_RDPConfig(OB_RDP_Level_2);
|
||||
|
||||
/* Warning: When enabling read protection level 2
|
||||
it's no more possible to go back to level 1 or 0
|
||||
* OB_RDP_Level_0: No protection
|
||||
* OB_RDP_Level_1 : Read protection of the memory
|
||||
* OB_RDP_Level_2 : Chip protection */
|
||||
FLASH_OB_Lock();
|
||||
}else
|
||||
{
|
||||
// 取消读保护会清空 Flash 内容,注意:要上电复位才可以使用IC
|
||||
FLASH_Unlock();
|
||||
FLASH_OB_RDPConfig(OB_RDP_Level_0);
|
||||
FLASH_OB_Lock();
|
||||
}return set;
|
||||
#endif
|
||||
}
|
|
@ -1,186 +0,0 @@
|
|||
#include "Kernel\Sys.h"
|
||||
#include "Device\I2C.h"
|
||||
|
||||
#include "RTL871x.h"
|
||||
|
||||
void HardI2C::OnInit()
|
||||
{
|
||||
I2C_TypeDef* g_I2Cs[] = I2CS;
|
||||
assert(_index < ArrayLength(g_I2Cs), "I2C::Init");
|
||||
_IIC = g_I2Cs[_index];
|
||||
|
||||
SCL.OpenDrain = true;
|
||||
SDA.OpenDrain = true;
|
||||
Pin pins[][2] = I2C_PINS;
|
||||
SCL.Set(pins[_index][0]);
|
||||
SDA.Set(pins[_index][1]);
|
||||
}
|
||||
|
||||
void HardI2C::OnOpen()
|
||||
{
|
||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1 << _index, ENABLE);
|
||||
#ifdef STM32F0
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
|
||||
#endif
|
||||
|
||||
//RCC_APB1PeriphResetCmd(sEE_I2C_CLK, ENABLE);
|
||||
//RCC_APB1PeriphResetCmd(sEE_I2C_CLK, DISABLE);
|
||||
|
||||
#ifdef STM32F0
|
||||
// 都在GPIO_AF_0分组内
|
||||
SCL.AFConfig(Port::AF_0);
|
||||
SDA.AFConfig(Port::AF_0);
|
||||
#elif defined(STM32F4)
|
||||
byte afs[] = { GPIO_AF_I2C1, GPIO_AF_I2C2, GPIO_AF_I2C3 };
|
||||
SCL.AFConfig((Port::GPIO_AF)afs[_index]);
|
||||
SDA.AFConfig((Port::GPIO_AF)afs[_index]);
|
||||
#endif
|
||||
SCL.Open();
|
||||
SDA.Open();
|
||||
|
||||
auto iic = (I2C_TypeDef*)_IIC;
|
||||
I2C_InitTypeDef i2c;
|
||||
I2C_StructInit(&i2c);
|
||||
|
||||
I2C_DeInit(iic); // 复位
|
||||
|
||||
// I2C_Timing
|
||||
// I2C_AnalogFilter
|
||||
// I2C_DigitalFilter
|
||||
// I2C_Mode
|
||||
// I2C_OwnAddress1
|
||||
// I2C_Ack
|
||||
// I2C_AcknowledgedAddress
|
||||
|
||||
/*i2c.I2C_AnalogFilter = I2C_AnalogFilter_Disable; // 关闭滤波器
|
||||
// i2c.I2C_DigitalFilter // 数字滤波器 不知道怎么设置 跟 cr1 的8-11位有关
|
||||
i2c.I2C_Mode =I2C_Mode_I2C; // IIC 模式
|
||||
// i2c.I2C_OwnAddress1
|
||||
i2c.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
|
||||
if(addressLen == ADDR_LEN_10)
|
||||
i2c.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_10bit;*/
|
||||
i2c.I2C_Mode = I2C_Mode_I2C; //设置I2C接口模式
|
||||
#ifndef STM32F0
|
||||
i2c.I2C_DutyCycle = I2C_DutyCycle_2; //设置I2C接口的高低电平周期
|
||||
#endif
|
||||
i2c.I2C_OwnAddress1 = Address; //设置I2C接口的主机地址。从设备需要设定的主机地址,而对于主机而言这里无所谓
|
||||
i2c.I2C_Ack = I2C_Ack_Enable; //设置是否开启ACK响应
|
||||
i2c.I2C_ClockSpeed = Speed; //速度
|
||||
|
||||
if(Address > 0xFF)
|
||||
i2c.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_10bit;
|
||||
else
|
||||
i2c.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
|
||||
|
||||
I2C_Cmd(iic, ENABLE);
|
||||
I2C_Init(iic, &i2c);
|
||||
}
|
||||
|
||||
void HardI2C::OnClose()
|
||||
{
|
||||
auto iic = (I2C_TypeDef*)_IIC;
|
||||
// sEE_I2C Peripheral Disable
|
||||
I2C_Cmd(iic, DISABLE);
|
||||
|
||||
// sEE_I2C DeInit
|
||||
I2C_DeInit(iic);
|
||||
|
||||
// sEE_I2C Periph clock disable
|
||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1 << _index, DISABLE);
|
||||
|
||||
SCL.Close();
|
||||
SDA.Close();
|
||||
}
|
||||
|
||||
void HardI2C::Start()
|
||||
{
|
||||
auto iic = (I2C_TypeDef*)_IIC;
|
||||
// 允许1字节1应答模式
|
||||
I2C_AcknowledgeConfig(iic, ENABLE);
|
||||
I2C_GenerateSTART(iic, ENABLE);
|
||||
|
||||
_Event = I2C_EVENT_MASTER_MODE_SELECT;
|
||||
WaitAck();
|
||||
}
|
||||
|
||||
void HardI2C::Stop()
|
||||
{
|
||||
auto iic = (I2C_TypeDef*)_IIC;
|
||||
// 最后一位后要关闭应答
|
||||
I2C_AcknowledgeConfig(iic, DISABLE);
|
||||
// 产生结束信号
|
||||
I2C_GenerateSTOP(iic, ENABLE);
|
||||
}
|
||||
|
||||
void HardI2C::Ack(bool ack)
|
||||
{
|
||||
I2C_AcknowledgeConfig((I2C_TypeDef*)_IIC, ack ? ENABLE : DISABLE);
|
||||
}
|
||||
|
||||
bool HardI2C::WaitAck(int retry)
|
||||
{
|
||||
if(!retry) retry = Retry;
|
||||
while(!I2C_CheckEvent((I2C_TypeDef*)_IIC, _Event))
|
||||
{
|
||||
if(--retry <= 0) return ++Error; // 超时处理
|
||||
}
|
||||
return retry > 0;
|
||||
}
|
||||
|
||||
bool HardI2C::SendAddress(int addr, bool tx)
|
||||
{
|
||||
auto iic = (I2C_TypeDef*)_IIC;
|
||||
if(tx)
|
||||
{
|
||||
// 向设备发送设备地址
|
||||
I2C_Send7bitAddress(iic, Address, I2C_Direction_Transmitter);
|
||||
|
||||
_Event = I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED;
|
||||
if(!WaitAck()) return false;
|
||||
|
||||
_Event = I2C_EVENT_MASTER_BYTE_TRANSMITTED;
|
||||
return I2C::SendSubAddr(addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 如果有子地址,需要先发送子地址。而子地址作为数据发送,需要首先设置为发送模式
|
||||
if(SubWidth > 0)
|
||||
{
|
||||
if(!SendAddress(addr, true)) return false;
|
||||
|
||||
// 重启会话
|
||||
Start();
|
||||
}
|
||||
|
||||
// 发送读地址
|
||||
I2C_Send7bitAddress(iic, Address, I2C_Direction_Receiver);
|
||||
|
||||
_Event = I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED;
|
||||
if(!WaitAck()) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void HardI2C::WriteByte(byte dat)
|
||||
{
|
||||
_Event = I2C_EVENT_MASTER_BYTE_TRANSMITTED;
|
||||
|
||||
I2C_SendData((I2C_TypeDef*)_IIC, dat);
|
||||
}
|
||||
|
||||
byte HardI2C::ReadByte()
|
||||
{
|
||||
_Event = I2C_EVENT_MASTER_BYTE_RECEIVED;
|
||||
|
||||
return I2C_ReceiveData((I2C_TypeDef*)_IIC);
|
||||
}
|
||||
|
||||
/*
|
||||
SDA 和SCL 都是双向线路都通过一个电流源或上拉电阻连接到正的电源电压。
|
||||
当总线空闲时这两条线路都是高电平。
|
||||
|
||||
SDA 线上的数据必须在时钟的高电平周期保持稳定。
|
||||
数据线的高或低电平状态只有在SCL线的时钟信号是低电平时才能改变。
|
||||
起始和停止例外,因此从机很容易区分起始和停止信号。
|
||||
*/
|
|
@ -1,83 +0,0 @@
|
|||
#include "Kernel\Sys.h"
|
||||
|
||||
#include "Kernel\Interrupt.h"
|
||||
//#include "SerialPort.h"
|
||||
|
||||
#include "RTL871x.h"
|
||||
|
||||
bool TInterrupt::OnActivate(short irq)
|
||||
{
|
||||
__DMB(); // asure table is written
|
||||
//NVIC->ICPR[irq >> 5] = 1 << (irq & 0x1F); // clear pending bit
|
||||
//NVIC->ISER[irq >> 5] = 1 << (irq & 0x1F); // set enable bit
|
||||
if(irq >= 0)
|
||||
{
|
||||
NVIC_ClearPendingIRQ((IRQn_Type)irq);
|
||||
NVIC_EnableIRQ((IRQn_Type)irq);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TInterrupt::OnDeactivate(short irq)
|
||||
{
|
||||
//NVIC->ICER[irq >> 5] = 1 << (irq & 0x1F); // clear enable bit */
|
||||
if(irq >= 0) NVIC_DisableIRQ((IRQn_Type)irq);
|
||||
return true;
|
||||
}
|
||||
|
||||
void TInterrupt::SetPriority(short irq, uint priority) const
|
||||
{
|
||||
NVIC_SetPriority((IRQn_Type)irq, priority);
|
||||
}
|
||||
|
||||
void TInterrupt::GetPriority(short irq) const
|
||||
{
|
||||
NVIC_GetPriority((IRQn_Type)irq);
|
||||
}
|
||||
|
||||
void TInterrupt::GlobalEnable() { __enable_irq(); }
|
||||
void TInterrupt::GlobalDisable(){ __disable_irq(); }
|
||||
bool TInterrupt::GlobalState() { return __get_PRIMASK(); }
|
||||
|
||||
#if !defined(TINY) && defined(STM32F0)
|
||||
#pragma arm section code = "SectionForSys"
|
||||
#endif
|
||||
|
||||
#if defined ( __CC_ARM )
|
||||
__ASM uint GetIPSR()
|
||||
{
|
||||
mrs r0,IPSR // exception number
|
||||
bx lr
|
||||
}
|
||||
#elif (defined (__GNUC__))
|
||||
uint32_t GetIPSR(void) __attribute__( ( naked ) );
|
||||
uint32_t GetIPSR(void)
|
||||
{
|
||||
uint32_t result=0;
|
||||
|
||||
__ASM volatile ("MRS r0, IPSR\n\t"
|
||||
"BX lr \n\t" : "=r" (result) );
|
||||
return(result);
|
||||
}
|
||||
#endif
|
||||
|
||||
// 是否在中断里面
|
||||
bool TInterrupt::IsHandler() { return GetIPSR() & 0x01; }
|
||||
|
||||
#ifdef TINY
|
||||
void FaultHandler() { }
|
||||
#else
|
||||
void UserHandler()
|
||||
{
|
||||
uint num = GetIPSR();
|
||||
Interrupt.Process(num);
|
||||
}
|
||||
#endif
|
||||
|
||||
void assert_failed(uint8_t* file, unsigned int line)
|
||||
{
|
||||
debug_printf("Assert Failed! Line %d, %s\r\n", line, file);
|
||||
|
||||
TInterrupt::Halt();
|
||||
}
|
|
@ -1,431 +0,0 @@
|
|||
#include "Kernel\Sys.h"
|
||||
#include "Kernel\Interrupt.h"
|
||||
#include "Device\Port.h"
|
||||
|
||||
#include "RTL871x.h"
|
||||
|
||||
#if defined(STM32F1) || defined(STM32F4)
|
||||
static const byte PORT_IRQns[] = {
|
||||
EXTI0_IRQn, EXTI1_IRQn, EXTI2_IRQn, EXTI3_IRQn, EXTI4_IRQn, // 5个基础的
|
||||
EXTI9_5_IRQn, EXTI9_5_IRQn, EXTI9_5_IRQn, EXTI9_5_IRQn, EXTI9_5_IRQn, // EXTI9_5
|
||||
EXTI15_10_IRQn, EXTI15_10_IRQn, EXTI15_10_IRQn, EXTI15_10_IRQn, EXTI15_10_IRQn, EXTI15_10_IRQn // EXTI15_10
|
||||
};
|
||||
#elif defined(STM32F0) || defined(GD32F150)
|
||||
static const byte PORT_IRQns[] = {
|
||||
EXTI0_1_IRQn, EXTI0_1_IRQn, // 基础
|
||||
EXTI2_3_IRQn, EXTI2_3_IRQn, // 基础
|
||||
EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn,
|
||||
EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn // EXTI15_10
|
||||
};
|
||||
#endif
|
||||
|
||||
//_force_inline GPIO_TypeDef* IndexToGroup(byte index) { return ((GPIO_TypeDef *) (GPIOA_BASE + (index << 10))); }
|
||||
//_force_inline byte GroupToIndex(GPIO_TypeDef* group) { return (byte)(((int)group - GPIOA_BASE) >> 10); }
|
||||
|
||||
/******************************** Port ********************************/
|
||||
|
||||
// 端口基本功能
|
||||
#define REGION_Port 1
|
||||
#ifdef REGION_Port
|
||||
|
||||
void* Port::IndexToGroup(byte index) { return ((GPIO_TypeDef *) (GPIOA_BASE + (index << 10))); }
|
||||
|
||||
void Port::OnOpenClock(Pin pin, bool flag)
|
||||
{
|
||||
int gi = pin >> 4;
|
||||
|
||||
FunctionalState fs = flag ? ENABLE : DISABLE;
|
||||
#if defined(STM32F0) || defined(GD32F150)
|
||||
RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOAEN << gi, fs);
|
||||
#elif defined(STM32F1)
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA << gi, fs);
|
||||
#elif defined(STM32F4)
|
||||
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA << gi, fs);
|
||||
#endif
|
||||
}
|
||||
|
||||
// 确定配置,确认用对象内部的参数进行初始化
|
||||
void Port::OpenPin()
|
||||
{
|
||||
GPIO_InitTypeDef gpio;
|
||||
// 特别要慎重,有些结构体成员可能因为没有初始化而酿成大错
|
||||
GPIO_StructInit(&gpio);
|
||||
|
||||
OnOpen(&gpio);
|
||||
GPIO_Init((GPIO_TypeDef*)Group, &gpio);
|
||||
}
|
||||
|
||||
void Port::OnOpen(void* param)
|
||||
{
|
||||
auto gpio = (GPIO_InitTypeDef*)param;
|
||||
gpio->GPIO_Pin = Mask;
|
||||
|
||||
#ifdef STM32F1
|
||||
// PA15/PB3/PB4 需要关闭JTAG
|
||||
switch(_Pin)
|
||||
{
|
||||
case PA15:
|
||||
case PB3:
|
||||
case PB4:
|
||||
{
|
||||
debug_printf("Close JTAG Pin P%c%d \r\n", _PIN_NAME(_Pin));
|
||||
|
||||
// PA15是jtag接口中的一员 想要使用 必须开启remap
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
|
||||
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Port::RemapConfig(uint param, bool sta)
|
||||
{
|
||||
#ifdef STM32F1
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
|
||||
GPIO_PinRemapConfig(param, sta ? ENABLE : DISABLE);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Port::AFConfig(GPIO_AF GPIO_AF) const
|
||||
{
|
||||
#if defined(STM32F0) || defined(GD32F150) || defined(STM32F4)
|
||||
assert(Opened, "打开后才能配置AF");
|
||||
|
||||
GPIO_PinAFConfig((GPIO_TypeDef*)Group, _PIN(_Pin), GPIO_AF);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Port::Read() const
|
||||
{
|
||||
if(_Pin == P0) return false;
|
||||
|
||||
return GPIO_ReadInputData((GPIO_TypeDef*)Group) & Mask;
|
||||
}
|
||||
#endif
|
||||
|
||||
/******************************** OutputPort ********************************/
|
||||
|
||||
// 输出端口
|
||||
#define REGION_Output 1
|
||||
#ifdef REGION_Output
|
||||
|
||||
void OutputPort::OpenPin(void* param)
|
||||
{
|
||||
#ifndef STM32F4
|
||||
assert(Speed == 2 || Speed == 10 || Speed == 50, "Speed");
|
||||
#else
|
||||
assert(Speed == 2 || Speed == 25 || Speed == 50 || Speed == 100, "Speed");
|
||||
#endif
|
||||
|
||||
auto gpio = (GPIO_InitTypeDef*)param;
|
||||
|
||||
switch(Speed)
|
||||
{
|
||||
case 2: gpio->GPIO_Speed = GPIO_Speed_2MHz; break;
|
||||
#ifndef STM32F4
|
||||
case 10: gpio->GPIO_Speed = GPIO_Speed_10MHz; break;
|
||||
#else
|
||||
case 25: gpio->GPIO_Speed = GPIO_Speed_25MHz; break;
|
||||
case 100: gpio->GPIO_Speed = GPIO_Speed_100MHz;break;
|
||||
#endif
|
||||
case 50: gpio->GPIO_Speed = GPIO_Speed_50MHz; break;
|
||||
}
|
||||
|
||||
#ifdef STM32F1
|
||||
gpio->GPIO_Mode = OpenDrain ? GPIO_Mode_Out_OD : GPIO_Mode_Out_PP;
|
||||
#else
|
||||
gpio->GPIO_Mode = GPIO_Mode_OUT;
|
||||
gpio->GPIO_OType = OpenDrain ? GPIO_OType_OD : GPIO_OType_PP;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool OutputPort::Read() const
|
||||
{
|
||||
if(Empty()) return false;
|
||||
|
||||
// 转为bool时会转为0/1
|
||||
bool rs = GPIO_ReadOutputData((GPIO_TypeDef*)Group) & Mask;
|
||||
return rs ^ Invert;
|
||||
}
|
||||
|
||||
bool OutputPort::ReadInput() const
|
||||
{
|
||||
if(Empty()) return false;
|
||||
|
||||
return Port::Read() ^ Invert;
|
||||
}
|
||||
|
||||
void OutputPort::Write(bool value) const
|
||||
{
|
||||
if(Empty()) return;
|
||||
|
||||
if(value ^ Invert)
|
||||
GPIO_SetBits((GPIO_TypeDef*)Group, Mask);
|
||||
else
|
||||
GPIO_ResetBits((GPIO_TypeDef*)Group, Mask);
|
||||
}
|
||||
|
||||
// 设置端口状态
|
||||
void OutputPort::Write(Pin pin, bool value)
|
||||
{
|
||||
if(pin == P0) return;
|
||||
|
||||
if(value)
|
||||
GPIO_SetBits(_GROUP(pin), _PORT(pin));
|
||||
else
|
||||
GPIO_ResetBits(_GROUP(pin), _PORT(pin));
|
||||
}
|
||||
|
||||
/******************************** AlternatePort ********************************/
|
||||
|
||||
void AlternatePort::OpenPin(void* param)
|
||||
{
|
||||
auto gpio = (GPIO_InitTypeDef*)param;
|
||||
|
||||
#ifdef STM32F1
|
||||
gpio->GPIO_Mode = OpenDrain ? GPIO_Mode_AF_OD : GPIO_Mode_AF_PP;
|
||||
#else
|
||||
gpio->GPIO_Mode = GPIO_Mode_AF;
|
||||
gpio->GPIO_OType = OpenDrain ? GPIO_OType_OD : GPIO_OType_PP;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/******************************** InputPort ********************************/
|
||||
|
||||
// 输入端口
|
||||
#define REGION_Input 1
|
||||
#ifdef REGION_Input
|
||||
/* 中断状态结构体 */
|
||||
/* 一共16条中断线,意味着同一条线每一组只能有一个引脚使用中断 */
|
||||
typedef struct TIntState
|
||||
{
|
||||
InputPort* Port;
|
||||
} IntState;
|
||||
|
||||
// 16条中断线
|
||||
static IntState States[16];
|
||||
static bool hasInitState = false;
|
||||
|
||||
int Bits2Index(ushort value)
|
||||
{
|
||||
for(int i=0; i<16; i++)
|
||||
{
|
||||
if(value & 0x01) return i;
|
||||
value >>= 1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define IT 1
|
||||
#ifdef IT
|
||||
void GPIO_ISR(int num) // 0 <= num <= 15
|
||||
{
|
||||
if(!hasInitState) return;
|
||||
|
||||
auto st = &States[num];
|
||||
// 如果未指定委托,则不处理
|
||||
if(!st || !st->Port) return;
|
||||
|
||||
uint bit = 1 << num;
|
||||
bool value;
|
||||
do {
|
||||
EXTI->PR = bit; // 重置挂起位
|
||||
value = st->Port->Read(); // 获取引脚状态
|
||||
} while (EXTI->PR & bit); // 如果再次挂起则重复
|
||||
// Read的时候已经计算倒置,这里不必重复计算
|
||||
st->Port->OnPress(value);
|
||||
}
|
||||
|
||||
void EXTI_IRQHandler(ushort num, void* param)
|
||||
{
|
||||
#if defined(STM32F1) || defined(STM32F4)
|
||||
// EXTI0 - EXTI4
|
||||
if(num <= EXTI4_IRQn)
|
||||
GPIO_ISR(num - EXTI0_IRQn);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
uint pending = EXTI->PR & EXTI->IMR;
|
||||
for(int i=0; i < 16 && pending != 0; i++, pending >>= 1)
|
||||
{
|
||||
if (pending & 1) GPIO_ISR(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void SetEXIT(int pinIndex, bool enable, InputPort::Trigger mode)
|
||||
{
|
||||
/* 配置EXTI中断线 */
|
||||
EXTI_InitTypeDef ext;
|
||||
EXTI_StructInit(&ext);
|
||||
ext.EXTI_Line = EXTI_Line0 << pinIndex;
|
||||
ext.EXTI_Mode = EXTI_Mode_Interrupt;
|
||||
if(mode == InputPort::Rising)
|
||||
ext.EXTI_Trigger = EXTI_Trigger_Rising; // 上升沿触发
|
||||
else if(mode == InputPort::Falling)
|
||||
ext.EXTI_Trigger = EXTI_Trigger_Falling; // 下降沿触发
|
||||
else
|
||||
ext.EXTI_Trigger = EXTI_Trigger_Rising_Falling; // 上升沿下降沿触发
|
||||
|
||||
ext.EXTI_LineCmd = enable ? ENABLE : DISABLE;
|
||||
EXTI_Init(&ext);
|
||||
}
|
||||
|
||||
void InputPort::OpenPin(void* param)
|
||||
{
|
||||
auto gpio = (GPIO_InitTypeDef*)param;
|
||||
|
||||
#ifdef STM32F1
|
||||
if(Floating)
|
||||
gpio->GPIO_Mode = GPIO_Mode_IN_FLOATING;
|
||||
else if(Pull == UP)
|
||||
gpio->GPIO_Mode = GPIO_Mode_IPU;
|
||||
else if(Pull == DOWN)
|
||||
gpio->GPIO_Mode = GPIO_Mode_IPD; // 这里很不确定,需要根据实际进行调整
|
||||
#else
|
||||
gpio->GPIO_Mode = GPIO_Mode_IN;
|
||||
//gpio->GPIO_OType = !Floating ? GPIO_OType_OD : GPIO_OType_PP;
|
||||
#endif
|
||||
}
|
||||
|
||||
// 是否独享中断号
|
||||
bool IsOnlyExOfInt(const InputPort* pt, int idx)
|
||||
{
|
||||
int s=0, e=0;
|
||||
#if defined(STM32F1) || defined(STM32F4)
|
||||
if(idx <= 4) return true;
|
||||
|
||||
if(idx <= 9)
|
||||
{
|
||||
s = 5;
|
||||
e = 9;
|
||||
}
|
||||
else if(idx <= 15)
|
||||
{
|
||||
s = 10;
|
||||
e = 15;
|
||||
}
|
||||
#elif defined(STM32F0) || defined(GD32F150)
|
||||
if(idx <= 1)
|
||||
{
|
||||
s = 0;
|
||||
e = 1;
|
||||
}
|
||||
else if(idx <= 3)
|
||||
{
|
||||
s = 2;
|
||||
e = 3;
|
||||
}
|
||||
else if(idx <= 15)
|
||||
{
|
||||
s = 4;
|
||||
e = 15;
|
||||
}
|
||||
#endif
|
||||
for(int i = s; i <= e; i++)
|
||||
if(States[i].Port != nullptr && States[i].Port != pt) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
InputPort::Trigger GetTrigger(InputPort::Trigger mode, bool invert)
|
||||
{
|
||||
if(invert && mode != InputPort::Both)
|
||||
{
|
||||
// 把上升沿下降沿换过来
|
||||
if(mode == InputPort::Rising)
|
||||
mode = InputPort::Falling;
|
||||
else if(mode == InputPort::Falling)
|
||||
mode = InputPort::Rising;
|
||||
}
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
void InputPort::ClosePin()
|
||||
{
|
||||
int idx = Bits2Index(Mask);
|
||||
|
||||
auto st = &States[idx];
|
||||
if(st->Port == this)
|
||||
{
|
||||
st->Port = nullptr;
|
||||
|
||||
SetEXIT(idx, false, GetTrigger(Mode, Invert));
|
||||
if(!IsOnlyExOfInt(this, idx))return;
|
||||
Interrupt.Deactivate(PORT_IRQns[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
// 注册回调 及中断使能
|
||||
bool InputPort::OnRegister()
|
||||
{
|
||||
// 检查并初始化中断线数组
|
||||
if(!hasInitState)
|
||||
{
|
||||
for(int i=0; i<16; i++)
|
||||
{
|
||||
States[i].Port = nullptr;
|
||||
}
|
||||
hasInitState = true;
|
||||
}
|
||||
|
||||
byte gi = _Pin >> 4;
|
||||
int idx = Bits2Index(Mask);
|
||||
auto st = &States[idx];
|
||||
|
||||
auto port = st->Port;
|
||||
// 检查是否已经注册到别的引脚上
|
||||
if(port != this && port != nullptr)
|
||||
{
|
||||
#if DEBUG
|
||||
debug_printf("中断线EXTI%d 不能注册到 P%c%d, 它已经注册到 P%c%d\r\n", gi, _PIN_NAME(_Pin), _PIN_NAME(port->_Pin));
|
||||
#endif
|
||||
|
||||
// 将来可能修改设计,即使注册失败,也可以开启一个短时间的定时任务,来替代中断输入
|
||||
return false;
|
||||
}
|
||||
st->Port = this;
|
||||
|
||||
//byte gi = _Pin >> 4;
|
||||
//int idx = Bits2Index(Mask);
|
||||
|
||||
// 打开时钟,选择端口作为端口EXTI时钟线
|
||||
#if defined(STM32F0) || defined(GD32F150) || defined(STM32F4)
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
|
||||
SYSCFG_EXTILineConfig(gi, idx);
|
||||
#elif defined(STM32F1)
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
|
||||
GPIO_EXTILineConfig(gi, idx);
|
||||
#endif
|
||||
|
||||
SetEXIT(idx, true, GetTrigger(Mode, Invert));
|
||||
|
||||
// 打开并设置EXTI中断为低优先级
|
||||
Interrupt.SetPriority(PORT_IRQns[idx], 1);
|
||||
|
||||
Interrupt.Activate(PORT_IRQns[idx], EXTI_IRQHandler, this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/******************************** AnalogInPort ********************************/
|
||||
|
||||
void AnalogInPort::OpenPin(void* param)
|
||||
{
|
||||
auto gpio = (GPIO_InitTypeDef*)param;
|
||||
|
||||
#ifdef STM32F1
|
||||
gpio->GPIO_Mode = GPIO_Mode_AIN; //
|
||||
#else
|
||||
gpio->GPIO_Mode = GPIO_Mode_AN;
|
||||
//gpio->GPIO_OType = !Floating ? GPIO_OType_OD : GPIO_OType_PP;
|
||||
#endif
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
#include "Device\Power.h"
|
||||
|
||||
#include "Device\WatchDog.h"
|
||||
|
||||
#include "RTL871x.h"
|
||||
|
||||
void Power::OnStop()
|
||||
{
|
||||
PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
|
||||
}
|
||||
|
||||
void Power::OnDeepSleep()
|
||||
{
|
||||
#ifdef STM32F0
|
||||
PWR_EnterSleepMode(PWR_SLEEPEntry_WFI);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Power::OnStandby()
|
||||
{
|
||||
PWR_EnterSTANDBYMode();
|
||||
}
|
|
@ -1,139 +0,0 @@
|
|||
#ifndef _RTL871x_H_
|
||||
#define _RTL871x_H_ 1
|
||||
|
||||
#define AUTOCONF_INCLUDED
|
||||
|
||||
//#include "hal_irqn.h"
|
||||
//#include "core_cm3.h"
|
||||
#include "rtl8195a.h"
|
||||
|
||||
// 获取组和针脚
|
||||
#define _GROUP(PIN) ((GPIO_TypeDef *) (GPIOA_BASE + (((PIN) & (uint16_t)0xF0) << 6)))
|
||||
|
||||
#ifdef STM32F10X_HD
|
||||
/* 通用同步/异步收发器(USART)针脚 ------------------------------------------------------------------*/
|
||||
#define UARTS {USART1, USART2, USART3, UART4, UART5}
|
||||
#define UART_IRQs {USART1_IRQn, USART2_IRQn, USART3_IRQn, UART4_IRQn, UART5_IRQn}
|
||||
#define UART_PINS {\
|
||||
/* TX RX CTS RTS */ \
|
||||
PA9, PA10,PA11,PA12,/* USART1 */ \
|
||||
PA2, PA3, PA0, PA1, /* USART2 */ \
|
||||
PB10,PB11,PB13,PB14,/* USART3 */ \
|
||||
PC10,PC11,P0, P0, /* UART4 */ \
|
||||
PC12, PD2,P0, P0, /* UART5 */ \
|
||||
}
|
||||
#define UART_PINS_FULLREMAP {\
|
||||
/* TX RX CTS RTS */ \
|
||||
PB6, PB7, PA11,PA12,/* USART1 AFIO_MAPR_USART1_REMAP */ \
|
||||
PD5, PD6, PD3, PD4, /* USART2 AFIO_MAPR_USART2_REMAP */ \
|
||||
PD8, PD9, PD11,PD12,/* USART3 AFIO_MAPR_USART3_REMAP_FULLREMAP */ \
|
||||
PC10,PC11,P0, P0, /* UART4 */ \
|
||||
PC12, PD2,P0, P0, /* UART5 */ \
|
||||
}
|
||||
#endif
|
||||
#ifdef STM32F10X_MD
|
||||
/* 通用同步/异步收发器(USART)针脚 ------------------------------------------------------------------*/
|
||||
#define UARTS {USART1, USART2, USART3}
|
||||
#define UART_IRQs {USART1_IRQn, USART2_IRQn, USART3_IRQn}
|
||||
#define UART_PINS {\
|
||||
/* TX RX CTS RTS */ \
|
||||
PA9, PA10,PA11,PA12,/* USART1 */ \
|
||||
PA2, PA3, PA0, PA1, /* USART2 */ \
|
||||
PB10,PB11,PB13,PB14,/* USART3 */ \
|
||||
}
|
||||
#define UART_PINS_FULLREMAP {\
|
||||
/* TX RX CTS RTS */ \
|
||||
PB6, PB7, PA11,PA12,/* USART1 AFIO_MAPR_USART1_REMAP */ \
|
||||
PD5, PD6, PD3, PD4, /* USART2 AFIO_MAPR_USART2_REMAP */ \
|
||||
PD8, PD9, PD11,PD12,/* USART3 AFIO_MAPR_USART3_REMAP_FULLREMAP */ \
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef STM32F10X_HD
|
||||
/* 定时器针脚 ------------------------------------------------------------------*/
|
||||
#define TIMS {TIM1, TIM2, TIM3, TIM4, TIM5, TIM6, TIM7, TIM8}
|
||||
#define TIM_IRQns {TIM1_UP_IRQn, TIM2_IRQn, TIM3_IRQn, TIM4_IRQn, TIM5_IRQn, TIM6_IRQn, TIM7_IRQn, TIM8_UP_IRQn}
|
||||
#define TIM_PINS {\
|
||||
PA8, PA9, PA10,PA11,/* TIM1 */ \
|
||||
PA0, PA1, PA2, PA3, /* TIM2 */ \
|
||||
PA6, PA7, PB0, PB1, /* TIM3 */ \
|
||||
PB6, PB7, PB8, PB9, /* TIM4 */ \
|
||||
PA0, PA1, PA2, PA3, /* TIM5 */ \
|
||||
P0, P0, P0, P0, /* TIM6 */ \
|
||||
P0, P0, P0, P0, /* TIM7 */ \
|
||||
PC6, PC7, PC8, PC9 /* TIM8 */ \
|
||||
}
|
||||
#define TIM_PINS_FULLREMAP {\
|
||||
PE9, PE11,PE13,PE14,/* TIM1 AFIO_MAPR_TIM1_REMAP_FULLREMAP */ \
|
||||
PA15,PB3, PB10,PB11,/* TIM2 AFIO_MAPR_TIM2_REMAP_FULLREMAP */ \
|
||||
PC6, PC7, PC8, PC9, /* TIM3 AFIO_MAPR_TIM3_REMAP_FULLREMAP */ \
|
||||
PD12,PD13,PD14,PD15,/* TIM4 AFIO_MAPR_TIM4_REMAP */ \
|
||||
PA0, PA1, PA2, PA3, /* TIM5 */ \
|
||||
P0, P0, P0, P0, /* TIM6 */ \
|
||||
P0, P0, P0, P0, /* TIM7 */ \
|
||||
PC6, PC7, PC8, PC9 /* TIM8 */ \
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef STM32F10X_MD
|
||||
/* 定时器针脚 ------------------------------------------------------------------*/
|
||||
#define TIMS {TIM1, TIM2, TIM3, TIM4, TIM5, TIM6, TIM7, TIM8}
|
||||
#define TIM_IRQns {TIM1_UP_IRQn, TIM2_IRQn, TIM3_IRQn, TIM4_IRQn}
|
||||
#define TIM_PINS {\
|
||||
PA8, PA9, PA10,PA11,/* TIM1 */ \
|
||||
PA0, PA1, PA2, PA3, /* TIM2 */ \
|
||||
PA6, PA7, PB0, PB1, /* TIM3 */ \
|
||||
PB6, PB7, PB8, PB9, /* TIM4 */ \
|
||||
}
|
||||
#define TIM_PINS_FULLREMAP {\
|
||||
PE9, PE11,PE13,PE14,/* TIM1 AFIO_MAPR_TIM1_REMAP_FULLREMAP */ \
|
||||
PA15,PB3, PB10,PB11,/* TIM2 AFIO_MAPR_TIM2_REMAP_FULLREMAP */ \
|
||||
PC6, PC7, PC8, PC9, /* TIM3 AFIO_MAPR_TIM3_REMAP_FULLREMAP */ \
|
||||
PD12,PD13,PD14,PD15,/* TIM4 AFIO_MAPR_TIM4_REMAP */ \
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* ADC(模拟/数字转换器)针脚 ------------------------------------------------------------------*/
|
||||
#define DAC_PINS {PA4,PA5}
|
||||
#define ADCS {ADC1,ADC2,ADC3}
|
||||
#define ADC_RCCS {RCC_APB2Periph_ADC1,RCC_APB2Periph_ADC2,RCC_APB2Periph_ADC3}
|
||||
#define ADC1_PINS {PA0,PA1,PA2,PA3,PA4,PA5,PA6,PA7,PB0,PB1,PC0,PC1,PC2,PC3,PC4,PC5}
|
||||
#define ADC3_PINS {PA0,PA1,PA2,PA3,PF6,PF7,PF8,PF9,PF10,PF3,PC0,PC1,PC2,PC3,PF4,PF5}
|
||||
|
||||
/* I2C总线针脚 ------------------------------------------------------------------*/
|
||||
#define I2CS {I2C1, I2C2}
|
||||
|
||||
#define I2C_PINS {\
|
||||
/* SCL SDA */\
|
||||
{ PB6, PB7 },\
|
||||
{ PB10, PB11 },\
|
||||
/*F1 REMAP{ PA8, PA9 },*/\
|
||||
}
|
||||
|
||||
/* 串行外设接口(SPI)针脚 ------------------------------------------------------------------*/
|
||||
#define SPIS {SPI1, SPI2, SPI3}
|
||||
//#define SPI_NSS_PINS {4, 28, 15} // PA4, PB12, PA15
|
||||
//#define SPI_SCLK_PINS {5, 29, 19} // PA5, PB13, PB3
|
||||
//#define SPI_MISO_PINS {6, 30, 20} // PA6, PB14, PB4
|
||||
//#define SPI_MOSI_PINS {7, 31, 21} // PA7, PB15, PB5
|
||||
|
||||
#define SPI_PINS_FULLREMAP {\
|
||||
/* NSS CLK MISO MOSI */\
|
||||
{PA4, PA5, PA6, PA7 },\
|
||||
{PB12,PB13,PB14,PB15},\
|
||||
{PA15,PB3, PB4, PB5 }\
|
||||
}
|
||||
|
||||
/* 控制器区域网络(CAN)针脚 ------------------------------------------------------------------*/
|
||||
#define CANS {CAN1, CAN2}
|
||||
// TX RX
|
||||
#define CAN_PINS {PA12, PA11} // AFIO_MAPR_CAN_REMAP_REMAP1
|
||||
#define CAN_PINS_REMAP2 {PB9, PB8 } // AFIO_MAPR_CAN_REMAP_REMAP2
|
||||
#define CAN_PINS_REMAP3 {PD1, PD0 } // AFIO_MAPR_CAN_REMAP_REMAP3
|
||||
|
||||
/* 通用串行总线(USB)针脚 ------------------------------------------------------------------*/
|
||||
|
||||
/* SDIO针脚 ------------------------------------------------------------------*/
|
||||
|
||||
#endif
|
|
@ -1,279 +0,0 @@
|
|||
#include "Kernel\Sys.h"
|
||||
#include "Kernel\Task.h"
|
||||
#include "Kernel\Interrupt.h"
|
||||
|
||||
#include "Device\SerialPort.h"
|
||||
|
||||
#include "RTL871x.h"
|
||||
|
||||
#define COM_DEBUG 0
|
||||
|
||||
const byte uart_irqs[] = UART_IRQs;
|
||||
|
||||
void SerialPort::OnInit()
|
||||
{
|
||||
_parity = USART_Parity_No;
|
||||
_dataBits = USART_WordLength_8b;
|
||||
_stopBits = USART_StopBits_1;
|
||||
}
|
||||
|
||||
bool SerialPort::OnSet()
|
||||
{
|
||||
USART_TypeDef* const g_Uart_Ports[] = UARTS;
|
||||
assert_param(_index < ArrayLength(g_Uart_Ports));
|
||||
|
||||
auto sp = g_Uart_Ports[_index];
|
||||
_port = sp;
|
||||
|
||||
// 根据端口实际情况决定打开状态
|
||||
return sp->CR1 & USART_CR1_UE;
|
||||
}
|
||||
|
||||
// 打开串口
|
||||
void SerialPort::OnOpen2()
|
||||
{
|
||||
Pin rx, tx;
|
||||
GetPins(&tx, &rx);
|
||||
|
||||
//串口引脚初始化
|
||||
_tx.Set(tx).Open();
|
||||
_rx.Init(rx, false).Open();
|
||||
|
||||
auto st = (USART_TypeDef*)_port;
|
||||
|
||||
// 不要关调试口,否则杯具
|
||||
if(_index != Sys.MessagePort) USART_DeInit(st);
|
||||
// USART_DeInit其实就是关闭时钟,这里有点多此一举。但为了安全起见,还是使用
|
||||
|
||||
// 检查重映射
|
||||
#ifdef STM32F1
|
||||
if(Remap)
|
||||
{
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
|
||||
switch (_index) {
|
||||
case 0: AFIO->MAPR |= AFIO_MAPR_USART1_REMAP; break;
|
||||
case 1: AFIO->MAPR |= AFIO_MAPR_USART2_REMAP; break;
|
||||
case 2: AFIO->MAPR |= AFIO_MAPR_USART3_REMAP_FULLREMAP; break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// 打开 UART 时钟。必须先打开串口时钟,才配置引脚
|
||||
#if defined(STM32F0) || defined(GD32F150)
|
||||
switch(_index)
|
||||
{
|
||||
case COM1: RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); break;
|
||||
case COM2: RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); break;
|
||||
default: break;
|
||||
}
|
||||
#else
|
||||
if (_index) { // COM2-5 on APB1
|
||||
RCC->APB1ENR |= RCC_APB1ENR_USART2EN >> 1 << _index;
|
||||
} else { // COM1 on APB2
|
||||
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(STM32F0) || defined(GD32F150)
|
||||
_tx.AFConfig(Port::AF_1);
|
||||
_rx.AFConfig(Port::AF_1);
|
||||
#elif defined(STM32F4)
|
||||
const byte afs[] = { GPIO_AF_USART1, GPIO_AF_USART2, GPIO_AF_USART3, GPIO_AF_UART4, GPIO_AF_UART5, GPIO_AF_USART6, GPIO_AF_UART7, GPIO_AF_UART8 };
|
||||
_tx.AFConfig((Port::GPIO_AF)afs[_index]);
|
||||
_rx.AFConfig((Port::GPIO_AF)afs[_index]);
|
||||
#endif
|
||||
|
||||
USART_InitTypeDef p;
|
||||
USART_StructInit(&p);
|
||||
p.USART_BaudRate = _baudRate;
|
||||
p.USART_WordLength = _dataBits;
|
||||
p.USART_StopBits = _stopBits;
|
||||
p.USART_Parity = _parity;
|
||||
USART_Init(st, &p);
|
||||
|
||||
// 串口接收中断配置,同时会打开过载错误中断
|
||||
USART_ITConfig(st, USART_IT_RXNE, ENABLE);
|
||||
//USART_ITConfig(st, USART_IT_PE, ENABLE);
|
||||
//USART_ITConfig(st, USART_IT_ERR, ENABLE);
|
||||
//USART_ITConfig(st, USART_IT_TXE, DISABLE);
|
||||
|
||||
//#if defined(STM32F0) || defined(GD32F150)
|
||||
// GD官方提供,因GD设计比ST严格,导致一些干扰被错误认为是溢出
|
||||
//USART_OverrunDetectionConfig(st, USART_OVRDetection_Disable);
|
||||
//#else
|
||||
// 打开中断,收发都要使用
|
||||
//const byte irqs[] = UART_IRQs;
|
||||
byte irq = uart_irqs[_index];
|
||||
Interrupt.SetPriority(irq, 0);
|
||||
Interrupt.Activate(irq, OnHandler, this);
|
||||
//#endif
|
||||
|
||||
USART_Cmd(st, ENABLE);//使能串口
|
||||
}
|
||||
|
||||
// 关闭端口
|
||||
void SerialPort::OnClose2()
|
||||
{
|
||||
auto st = (USART_TypeDef*)_port;
|
||||
USART_Cmd(st, DISABLE);
|
||||
USART_DeInit(st);
|
||||
|
||||
_tx.Close();
|
||||
_rx.Close();
|
||||
|
||||
//const byte irqs[] = UART_IRQs;
|
||||
byte irq = uart_irqs[_index];
|
||||
Interrupt.Deactivate(irq);
|
||||
|
||||
// 检查重映射
|
||||
#ifdef STM32F1
|
||||
if(Remap)
|
||||
{
|
||||
switch (_index) {
|
||||
case 0: AFIO->MAPR &= ~AFIO_MAPR_USART1_REMAP; break;
|
||||
case 1: AFIO->MAPR &= ~AFIO_MAPR_USART2_REMAP; break;
|
||||
case 2: AFIO->MAPR &= ~AFIO_MAPR_USART3_REMAP_FULLREMAP; break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// 发送单一字节数据
|
||||
uint SerialPort::SendData(byte data, uint times)
|
||||
{
|
||||
/*
|
||||
在USART_DR寄存器中写入了最后一个数据字后,在关闭USART模块之前或设置微控制器进入低功耗模式之前,
|
||||
必须先等待TC=1。使用下列软件过程清除TC位:
|
||||
1.读一次USART_SR寄存器;
|
||||
2.写一次USART_DR寄存器。
|
||||
*/
|
||||
auto st = (USART_TypeDef*)_port;
|
||||
USART_SendData(st, (ushort)data);
|
||||
// 等待发送完毕
|
||||
while(USART_GetFlagStatus(st, USART_FLAG_TXE) == RESET && --times > 0);
|
||||
if(!times) Error++;
|
||||
|
||||
return times;
|
||||
}
|
||||
|
||||
// 向某个端口写入数据。如果size为0,则把data当作字符串,一直发送直到遇到\0为止
|
||||
void SerialPort::OnWrite2()
|
||||
{
|
||||
// 打开串口发送
|
||||
USART_ITConfig((USART_TypeDef*)_port, USART_IT_TXE, ENABLE);
|
||||
}
|
||||
|
||||
#if !defined(TINY) && defined(STM32F0)
|
||||
#pragma arm section code = "SectionForSys"
|
||||
#endif
|
||||
|
||||
void SerialPort::OnTxHandler()
|
||||
{
|
||||
if(!Tx.Empty())
|
||||
USART_SendData((USART_TypeDef*)_port, (ushort)Tx.Pop());
|
||||
else
|
||||
{
|
||||
USART_ITConfig((USART_TypeDef*)_port, USART_IT_TXE, DISABLE);
|
||||
|
||||
Set485(false);
|
||||
}
|
||||
}
|
||||
|
||||
void SerialPort::OnRxHandler()
|
||||
{
|
||||
// 串口接收中断必须以极快的速度完成,否则会出现丢数据的情况
|
||||
// 判断缓冲区足够最小值以后才唤醒任务,减少时间消耗
|
||||
// 缓冲区里面别用%,那会产生非常耗时的除法运算
|
||||
byte dat = (byte)USART_ReceiveData((USART_TypeDef*)_port);
|
||||
Rx.Push(dat);
|
||||
|
||||
// 收到数据,开启任务调度。延迟_byteTime,可能还有字节到来
|
||||
//!!! 暂时注释任务唤醒,避免丢数据问题
|
||||
if(_taskidRx && Rx.Length() >= MinSize)
|
||||
{
|
||||
//Sys.SetTask(_taskidRx, true, (ByteTime >> 10) + 1);
|
||||
((Task*)_task)->Set(true, 20);
|
||||
}
|
||||
}
|
||||
|
||||
// 真正的串口中断函数
|
||||
void SerialPort::OnHandler(ushort num, void* param)
|
||||
{
|
||||
auto sp = (SerialPort*)param;
|
||||
auto st = (USART_TypeDef*)sp->_port;
|
||||
|
||||
//#if !(defined(STM32F0) || defined(GD32F150))
|
||||
if(USART_GetITStatus(st, USART_IT_TXE) != RESET) sp->OnTxHandler();
|
||||
//#endif
|
||||
// 接收中断
|
||||
if(USART_GetITStatus(st, USART_IT_RXNE) != RESET) sp->OnRxHandler();
|
||||
// 溢出
|
||||
if(USART_GetFlagStatus(st, USART_FLAG_ORE) != RESET)
|
||||
{
|
||||
//USART_ClearFlag(st, USART_FLAG_ORE); // ST 库文件 ClearFlag 不许动 USART_FLAG_ORE 寄存器
|
||||
// 读取并扔到错误数据
|
||||
USART_ReceiveData(st);
|
||||
sp->Error++;
|
||||
//debug_printf("Serial%d 溢出 \r\n", sp->_index + 1);
|
||||
}
|
||||
/*if(USART_GetFlagStatus(st, USART_FLAG_NE) != RESET) USART_ClearFlag(st, USART_FLAG_NE);
|
||||
if(USART_GetFlagStatus(st, USART_FLAG_FE) != RESET) USART_ClearFlag(st, USART_FLAG_FE);
|
||||
if(USART_GetFlagStatus(st, USART_FLAG_PE) != RESET) USART_ClearFlag(st, USART_FLAG_PE);*/
|
||||
}
|
||||
|
||||
#pragma arm section code
|
||||
|
||||
// 获取引脚
|
||||
void SerialPort::GetPins(Pin* txPin, Pin* rxPin)
|
||||
{
|
||||
*rxPin = *txPin = P0;
|
||||
|
||||
const Pin g_Uart_Pins[] = UART_PINS;
|
||||
const Pin* p = g_Uart_Pins;
|
||||
#ifdef STM32F1
|
||||
const Pin g_Uart_Pins_Map[] = UART_PINS_FULLREMAP;
|
||||
if(Remap) p = g_Uart_Pins_Map;
|
||||
#endif
|
||||
|
||||
int n = _index << 2;
|
||||
*txPin = p[n];
|
||||
*rxPin = p[n + 1];
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
extern SerialPort* _printf_sp;
|
||||
bool isInFPutc;
|
||||
|
||||
/* 重载fputc可以让用户程序使用printf函数 */
|
||||
int fputc(int ch, FILE *f)
|
||||
{
|
||||
#if DEBUG
|
||||
if(Sys.Clock == 0) return ch;
|
||||
|
||||
int idx = Sys.MessagePort;
|
||||
if(idx == COM_NONE) return ch;
|
||||
|
||||
if(isInFPutc) return ch;
|
||||
isInFPutc = true;
|
||||
|
||||
USART_TypeDef* g_Uart_Ports[] = UARTS;
|
||||
auto port = g_Uart_Ports[idx];
|
||||
|
||||
// 检查并打开串口
|
||||
if((port->CR1 & USART_CR1_UE) != USART_CR1_UE)
|
||||
{
|
||||
_printf_sp = SerialPort::GetMessagePort();
|
||||
}
|
||||
|
||||
if(_printf_sp)
|
||||
{
|
||||
byte b = ch;
|
||||
_printf_sp->Write(Buffer(&b, 1));
|
||||
}
|
||||
|
||||
isInFPutc = false;
|
||||
#endif
|
||||
return ch;
|
||||
}
|
||||
}
|
|
@ -1,159 +0,0 @@
|
|||
#include "Kernel\Sys.h"
|
||||
|
||||
#include "Device\Spi.h"
|
||||
|
||||
#include "RTL871x.h"
|
||||
|
||||
int Spi::GetPre(int index, uint& speedHz)
|
||||
{
|
||||
// 自动计算稍低于速度speedHz的分频
|
||||
ushort pre = SPI_BaudRatePrescaler_2;
|
||||
uint clock = Sys.Clock >> 1;
|
||||
while(pre <= SPI_BaudRatePrescaler_256)
|
||||
{
|
||||
if(clock <= speedHz) break;
|
||||
clock >>= 1;
|
||||
pre += (SPI_BaudRatePrescaler_4 - SPI_BaudRatePrescaler_2);
|
||||
}
|
||||
if(pre > SPI_BaudRatePrescaler_256)
|
||||
{
|
||||
debug_printf("Spi%d::Init Error! speedHz=%d mush be dived with %d\r\n", index, speedHz, Sys.Clock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
speedHz = clock;
|
||||
|
||||
return pre;
|
||||
}
|
||||
|
||||
void Spi::OnInit()
|
||||
{
|
||||
SPI_TypeDef* g_Spis[] = SPIS;
|
||||
assert_param(_index < ArrayLength(g_Spis));
|
||||
|
||||
_SPI = g_Spis[_index];
|
||||
|
||||
Pin g_Spi_Pins_Map[][4] = SPI_PINS_FULLREMAP;
|
||||
auto ps = g_Spi_Pins_Map[_index]; //选定spi引脚
|
||||
Buffer(Pins, sizeof(Pins)) = ps;
|
||||
}
|
||||
|
||||
void Spi::OnOpen()
|
||||
{
|
||||
// 自动计算稍低于速度speedHz的分频
|
||||
uint speedHz = Speed;
|
||||
int pre = GetPre(_index, speedHz);
|
||||
if(pre == -1) return;
|
||||
|
||||
// 使能SPI时钟
|
||||
switch(_index)
|
||||
{
|
||||
case 0: RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); break;
|
||||
#if defined(STM32F1) || defined(STM32F4)
|
||||
case 1: RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE); break;
|
||||
case 2: RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE); break;
|
||||
#if defined(STM32F4)
|
||||
case 3: RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI4, ENABLE); break;
|
||||
case 4: RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI5, ENABLE); break;
|
||||
case 5: RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI6, ENABLE); break;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(STM32F0)
|
||||
// SPI都在GPIO_AF_0分组内
|
||||
_clk.AFConfig(Port::AF_0);
|
||||
_miso.AFConfig(Port::AF_0);
|
||||
_mosi.AFConfig(Port::AF_0);
|
||||
#elif defined(STM32F4)
|
||||
const byte afs[] = { GPIO_AF_SPI1, GPIO_AF_SPI2, GPIO_AF_SPI3, GPIO_AF_SPI4, GPIO_AF_SPI5, GPIO_AF_SPI6 };
|
||||
_clk.AFConfig((Port::GPIO_AF)afs[_index]);
|
||||
_miso.AFConfig((Port::GPIO_AF)afs[_index]);
|
||||
_mosi.AFConfig((Port::GPIO_AF)afs[_index]);
|
||||
#endif
|
||||
|
||||
Stop();
|
||||
SPI_I2S_DeInit((SPI_TypeDef*)_SPI);
|
||||
//SPI_DeInit((SPI_TypeDef*)_SPI); // SPI_I2S_DeInit的宏定义别名
|
||||
|
||||
SPI_InitTypeDef sp;
|
||||
SPI_StructInit(&sp);
|
||||
sp.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //双线全双工
|
||||
sp.SPI_Mode = SPI_Mode_Master; // 主模式
|
||||
sp.SPI_DataSize = SPI_DataSize_8b; // 数据大小8位 SPI发送接收8位帧结构
|
||||
sp.SPI_CPOL = SPI_CPOL_Low; // 时钟极性,空闲时为低
|
||||
sp.SPI_CPHA = SPI_CPHA_1Edge; // 第1个边沿有效,上升沿为采样时刻
|
||||
sp.SPI_NSS = SPI_NSS_Soft; // NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
|
||||
sp.SPI_BaudRatePrescaler = pre; // 8分频,9MHz 定义波特率预分频的值
|
||||
sp.SPI_FirstBit = SPI_FirstBit_MSB; // 高位在前。指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
|
||||
sp.SPI_CRCPolynomial = 7; // CRC值计算的多项式
|
||||
|
||||
SPI_Init((SPI_TypeDef*)_SPI, &sp);
|
||||
SPI_Cmd((SPI_TypeDef*)_SPI, ENABLE);
|
||||
}
|
||||
|
||||
void Spi::OnClose()
|
||||
{
|
||||
SPI_Cmd((SPI_TypeDef*)_SPI, DISABLE);
|
||||
SPI_I2S_DeInit((SPI_TypeDef*)_SPI);
|
||||
}
|
||||
|
||||
byte Spi::Write(byte data)
|
||||
{
|
||||
if(!Opened) Open();
|
||||
|
||||
auto si = (SPI_TypeDef*)_SPI;
|
||||
int retry = Retry;
|
||||
while (SPI_I2S_GetFlagStatus(si, SPI_I2S_FLAG_TXE) == RESET)
|
||||
{
|
||||
if(--retry <= 0) return ++Error; // 超时处理
|
||||
}
|
||||
|
||||
#ifndef STM32F0
|
||||
SPI_I2S_SendData(si, data);
|
||||
#else
|
||||
SPI_SendData8(si, data);
|
||||
#endif
|
||||
|
||||
retry = Retry;
|
||||
while (SPI_I2S_GetFlagStatus(si, SPI_I2S_FLAG_RXNE) == RESET) //是否发送成功
|
||||
{
|
||||
if(--retry <= 0) return ++Error; // 超时处理
|
||||
}
|
||||
#ifndef STM32F0
|
||||
return SPI_I2S_ReceiveData(si);
|
||||
#else
|
||||
return SPI_ReceiveData8(si); //返回通过SPIx最近接收的数据
|
||||
#endif
|
||||
}
|
||||
|
||||
ushort Spi::Write16(ushort data)
|
||||
{
|
||||
if(!Opened) Open();
|
||||
|
||||
auto si = (SPI_TypeDef*)_SPI;
|
||||
// 双字节操作,超时次数加倍
|
||||
int retry = Retry << 1;
|
||||
while (SPI_I2S_GetFlagStatus(si, SPI_I2S_FLAG_TXE) == RESET)
|
||||
{
|
||||
if(--retry <= 0) return ++Error; // 超时处理
|
||||
}
|
||||
|
||||
#ifndef STM32F0
|
||||
SPI_I2S_SendData(si, data);
|
||||
#else
|
||||
SPI_I2S_SendData16(si, data);
|
||||
#endif
|
||||
|
||||
retry = Retry << 1;
|
||||
while (SPI_I2S_GetFlagStatus(si, SPI_I2S_FLAG_RXNE) == RESET)
|
||||
{
|
||||
if(--retry <= 0) return ++Error; // 超时处理
|
||||
}
|
||||
|
||||
#ifndef STM32F0
|
||||
return SPI_I2S_ReceiveData(si);
|
||||
#else
|
||||
return SPI_I2S_ReceiveData16(si);
|
||||
#endif
|
||||
}
|
|
@ -1,213 +0,0 @@
|
|||
#include "Kernel\Sys.h"
|
||||
|
||||
#include "RTL871x.h"
|
||||
|
||||
extern uint __heap_base;
|
||||
extern uint __heap_limit;
|
||||
extern uint __initial_sp;
|
||||
extern uint __microlib_freelist;
|
||||
extern uint __microlib_freelist_initialised;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
__IO uint32_t IDCODE;
|
||||
__IO uint32_t CR;
|
||||
}DBGMCU_TypeDef;
|
||||
#define DBGMCU_BASE ((uint32_t)0xE0042000) /*!< Debug MCU registers base address */
|
||||
#define DBGMCU ((DBGMCU_TypeDef *) DBGMCU_BASE)
|
||||
|
||||
void TSys::OnInit()
|
||||
{
|
||||
Clock = 83000000;
|
||||
CystalClock = 12000000; // 晶振时钟
|
||||
MessagePort = COM1; // COM1;
|
||||
|
||||
void* p = (void*)0x1FFFF7AC; // 手册里搜索UID,优先英文手册
|
||||
Buffer::Copy(ID, p, ArrayLength(ID));
|
||||
|
||||
CPUID = SCB->CPUID;
|
||||
uint mcuid = DBGMCU->IDCODE; // MCU编码。低字设备版本,高字子版本
|
||||
RevID = mcuid >> 16;
|
||||
DevID = mcuid & 0x0FFF;
|
||||
|
||||
FlashSize = 0x1000000; // 容量
|
||||
RAMSize = 0x800000;
|
||||
}
|
||||
|
||||
void TSys::InitClock()
|
||||
{
|
||||
}
|
||||
|
||||
// 堆起始地址,前面是静态分配内存
|
||||
uint TSys::HeapBase() const
|
||||
{
|
||||
return (uint)&__heap_base;
|
||||
}
|
||||
|
||||
// 栈顶,后面是初始化不清零区域
|
||||
uint TSys::StackTop() const
|
||||
{
|
||||
return 0x1000000 + (RAMSize << 10) - 0x40;
|
||||
}
|
||||
|
||||
void TSys::SetStackTop(uint addr)
|
||||
{
|
||||
__set_MSP(addr);
|
||||
}
|
||||
|
||||
#if !defined(TINY) && defined(STM32F0) && defined(DEBUG)
|
||||
#pragma arm section code = "SectionForSys"
|
||||
#endif
|
||||
|
||||
bool TSys::CheckMemory() const
|
||||
{
|
||||
#if DEBUG
|
||||
uint msp = __get_MSP();
|
||||
|
||||
//if(__microlib_freelist >= msp) return false;
|
||||
assert(__microlib_freelist + 0x40 < msp, "堆栈相互穿透,内存已用完!可能是堆分配或野指针带来了内存泄漏!");
|
||||
|
||||
// 如果堆只剩下64字节,则报告失败,要求用户扩大堆空间以免不测
|
||||
//uint end = SRAM_BASE + (RAMSize << 10);
|
||||
//if(__microlib_freelist + 0x40 >= end) return false;
|
||||
assert(__microlib_freelist + 0x40 < SRAM_BASE + (RAMSize << 10), "堆栈相互穿透,内存已用完!一定是堆分配带来了内存泄漏!");
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#pragma arm section code
|
||||
|
||||
#if DEBUG
|
||||
typedef struct
|
||||
{
|
||||
byte Revision:4; // The p value in the Rnpn product revision identifier, indicates patch release.0x0: patch 0
|
||||
ushort PartNo:12; // Part number of the processor. 0xC20: Cortex-M0
|
||||
byte Constant:4; // Constant that defines the architecture of the processor. 0xC: ARMv6-M architecture
|
||||
byte Variant:4; // Variant number: The r value in the Rnpn product revision identifier. 0x0: revision 0
|
||||
byte Implementer; // Implementer code. 0x41 ARM
|
||||
}ST_CPUID;
|
||||
#endif
|
||||
|
||||
void TSys::OnShowInfo() const
|
||||
{
|
||||
#if DEBUG
|
||||
debug_printf("SmartOS::");
|
||||
bool IsGD = Get_JTAG_ID() == 0x7A3;
|
||||
if(IsGD)
|
||||
debug_printf("GD32");
|
||||
else
|
||||
debug_printf("STM32");
|
||||
|
||||
auto cpu = (ST_CPUID*)&CPUID;
|
||||
if(DevID > 0)
|
||||
{
|
||||
if(DevID == 0x410)
|
||||
{
|
||||
if(IsGD && RevID == 0x1303)
|
||||
{
|
||||
if(Clock == 48000000)
|
||||
debug_printf("F130");
|
||||
else
|
||||
debug_printf("F150");
|
||||
}
|
||||
#ifdef STM32F1
|
||||
else
|
||||
debug_printf("F103");
|
||||
#endif
|
||||
}
|
||||
#ifdef STM32F1
|
||||
else if(DevID == 0x412 || DevID == 0x414 || DevID == 0x430)
|
||||
debug_printf("F103");
|
||||
else if(DevID == 0x418)
|
||||
debug_printf("F107");
|
||||
else if(DevID == 0x412)
|
||||
debug_printf("F130");
|
||||
#endif
|
||||
#ifdef STM32F4
|
||||
else if(DevID == 0x413)
|
||||
debug_printf("F407");
|
||||
#endif
|
||||
else if(DevID == 0x440 || DevID == 0x444) // F030x4/F030x6=0x444 F030x8=0x440
|
||||
debug_printf("F030/F051");
|
||||
else
|
||||
debug_printf("F%03x", DevID);
|
||||
}
|
||||
else if(CPUID > 0)
|
||||
{
|
||||
if(Clock == 48000000)
|
||||
debug_printf("F130/F150");
|
||||
#ifdef STM32F1
|
||||
else
|
||||
debug_printf("F103");
|
||||
#endif
|
||||
}
|
||||
|
||||
// 暂时不知道怎么计算引脚,一般F4/F6/C8CB/RB/VC/VE
|
||||
if(_Index < 2)
|
||||
debug_printf("F");
|
||||
else if(_Index < 4)
|
||||
debug_printf("C");
|
||||
else if(_Index < 6)
|
||||
debug_printf("R");
|
||||
else
|
||||
debug_printf("V");
|
||||
debug_printf("%c", MemNames[_Index]);
|
||||
//debug_printf("\r\n");
|
||||
|
||||
// 系统信息
|
||||
//debug_printf(" %dMHz Flash:%dk RAM:%dk\r\n", Clock/1000000, FlashSize, RAMSize);
|
||||
// 获取当前频率
|
||||
debug_printf(" %dMHz Flash:%dk RAM:%dk\r\n", RCC_GetSysClock()/1000000, FlashSize, RAMSize);
|
||||
//debug_printf("\r\n");
|
||||
debug_printf("DevID:0x%04X RevID:0x%04X \r\n", DevID, RevID);
|
||||
|
||||
debug_printf("CPUID:0x%08X", CPUID);
|
||||
if(cpu->Implementer == 0x41) debug_printf(" ARM:");
|
||||
if(cpu->Constant == 0x0C)
|
||||
debug_printf(" ARMv6-M");
|
||||
else if(cpu->Constant == 0x0F)
|
||||
debug_printf(" ARMv7-M");
|
||||
if((cpu->PartNo & 0x0FF0) == 0x0C20) debug_printf(" Cortex-M%d:", cpu->PartNo & 0x0F);
|
||||
debug_printf(" R%dp%d", cpu->Revision, cpu->Variant);
|
||||
debug_printf("\r\n");
|
||||
|
||||
// 输出堆信息
|
||||
uint start = (uint)&__heap_base;
|
||||
// F4有64k的CCM内存
|
||||
#if defined(STM32F4)
|
||||
if(start < 0x20000000) start = 0x20000000;
|
||||
#endif
|
||||
uint end = SRAM_BASE + (RAMSize << 10);
|
||||
uint size = end - start;
|
||||
debug_printf("Heap :(0x%08x, 0x%08x) = 0x%x (%dk)\r\n", start, end, size, size >> 10);
|
||||
start = (uint)&__heap_limit;
|
||||
#if defined(STM32F4)
|
||||
if(start < 0x20000000) start = 0x20000000;
|
||||
#endif
|
||||
//end = 0x20000000 + (RAMSize << 10);
|
||||
size = end - start;
|
||||
debug_printf("Stack:(0x%08x, 0x%08x) = 0x%x (%dk)\r\n", start, end, size, size >> 10);
|
||||
|
||||
if(IsGD) debug_printf("ChipType:0x%08X %s\r\n", *(uint*)0x40022100, (cstring)0x40022100);
|
||||
#endif
|
||||
}
|
||||
|
||||
void TSys::Reset() const { NVIC_SystemReset(); }
|
||||
|
||||
void TSys::OnStart()
|
||||
{
|
||||
#if !DEBUG
|
||||
//WatchDog::Start();
|
||||
#endif
|
||||
}
|
||||
|
||||
/******************************** 临界区 ********************************/
|
||||
|
||||
void EnterCritical() { __disable_irq(); }
|
||||
void ExitCritical() { __enable_irq(); }
|
||||
|
||||
/******************************** REV ********************************/
|
||||
|
||||
uint _REV(uint value) { return __REV(value); }
|
||||
ushort _REV16(ushort value) { return __REV16(value); }
|
|
@ -1,53 +0,0 @@
|
|||
#include "Kernel\Sys.h"
|
||||
#include "Kernel\Interrupt.h"
|
||||
#include "Kernel\TTime.h"
|
||||
#include "Device\Timer.h"
|
||||
|
||||
#include "RTL871x.h"
|
||||
#include "timer_api.h"
|
||||
|
||||
#define TIME_DEBUG 0
|
||||
|
||||
/************************************************ TTime ************************************************/
|
||||
|
||||
static gtimer_t _timer;
|
||||
|
||||
static void OnTimerHandler(uint param)
|
||||
{
|
||||
// 重新加载,清零
|
||||
gtimer_reload(&_timer, 1000);
|
||||
|
||||
auto& time = *(TTime*)param;
|
||||
// 累加计数
|
||||
time.Seconds += 1;
|
||||
time.Milliseconds += 1000;
|
||||
|
||||
// 定期保存Ticks到后备RTC寄存器
|
||||
if(time.OnSave) time.OnSave();
|
||||
}
|
||||
|
||||
void TTime::Init()
|
||||
{
|
||||
auto ti = &_timer;
|
||||
gtimer_init(ti, TIMER0);
|
||||
gtimer_start_periodical(ti, 1000, (void*)OnTimerHandler, (uint)this);
|
||||
}
|
||||
|
||||
void TTime::OnHandler(ushort num, void* param)
|
||||
{
|
||||
}
|
||||
|
||||
// 当前滴答时钟
|
||||
uint TTime::CurrentTicks() const
|
||||
{
|
||||
return gtimer_read_tick(&_timer);
|
||||
}
|
||||
|
||||
// 当前毫秒数
|
||||
UInt64 TTime::Current() const
|
||||
{
|
||||
UInt64 ms = gtimer_read_tick(&_timer) * 1000;
|
||||
ms >>= 15;
|
||||
|
||||
return Milliseconds + ms;
|
||||
}
|
|
@ -1,111 +0,0 @@
|
|||
#include "Kernel\Sys.h"
|
||||
#include "Kernel\Interrupt.h"
|
||||
|
||||
#include "Device\Timer.h"
|
||||
|
||||
extern "C" {
|
||||
#include "RTL871x.h"
|
||||
#include "timer_api.h"
|
||||
}
|
||||
|
||||
static uint const g_ts[] = { TIMER0, TIMER1, TIMER2, TIMER3, TIMER4 };
|
||||
static gtimer_t* g_Timers[] = { nullptr, nullptr, nullptr, nullptr, nullptr };
|
||||
const byte Timer::TimerCount = ArrayLength(g_Timers);
|
||||
|
||||
const void* Timer::GetTimer(byte idx)
|
||||
{
|
||||
return g_Timers[idx];
|
||||
}
|
||||
|
||||
void Timer::OnInit()
|
||||
{
|
||||
assert(_index <= ArrayLength(g_Timers), "定时器索引越界");
|
||||
|
||||
auto ti = g_Timers[_index];
|
||||
if(!ti)
|
||||
{
|
||||
ti = new gtimer_t();
|
||||
gtimer_init(ti, g_ts[_index]);
|
||||
g_Timers[_index] = ti;
|
||||
}
|
||||
_Timer = ti;
|
||||
}
|
||||
|
||||
void Timer::Config()
|
||||
{
|
||||
TS("Timer::Config");
|
||||
|
||||
// 配置时钟
|
||||
auto ti = (gtimer_t*)_Timer;
|
||||
ti->is_periodcal = _TRUE;
|
||||
gtimer_reload(ti, Period);
|
||||
}
|
||||
|
||||
void Timer::OnOpen()
|
||||
{
|
||||
debug_printf("Timer%d::Open Period=%d\r\n", _index + 1, Period);
|
||||
|
||||
Config();
|
||||
|
||||
gtimer_start((gtimer_t*)_Timer);
|
||||
}
|
||||
|
||||
void Timer::OnClose()
|
||||
{
|
||||
gtimer_stop((gtimer_t*)_Timer);
|
||||
}
|
||||
|
||||
void Timer::ClockCmd(int idx, bool state)
|
||||
{
|
||||
}
|
||||
|
||||
// 设置频率,自动计算预分频
|
||||
void Timer::SetFrequency(uint frequency)
|
||||
{
|
||||
Prescaler = 1;
|
||||
Period = frequency;
|
||||
|
||||
// 如果已启动定时器,则重新配置一下,让新设置生效
|
||||
if(Opened) gtimer_reload((gtimer_t*)_Timer, Period);
|
||||
}
|
||||
|
||||
uint Timer::GetCounter()
|
||||
{
|
||||
return gtimer_read_tick((gtimer_t*)_Timer);
|
||||
}
|
||||
|
||||
void Timer::SetCounter(uint cnt)
|
||||
{
|
||||
// 仅支持0us
|
||||
if(!cnt) gtimer_reload((gtimer_t*)_Timer, cnt);
|
||||
}
|
||||
|
||||
static void OnTimerHandler(uint param)
|
||||
{
|
||||
auto timer = (Timer*)param;
|
||||
timer->OnInterrupt();
|
||||
}
|
||||
|
||||
void Timer::SetHandler(bool set)
|
||||
{
|
||||
auto ti = (gtimer_t*)_Timer;
|
||||
if(set)
|
||||
{
|
||||
ti->handler = (void*)OnTimerHandler;
|
||||
ti->hid = (uint)this;
|
||||
}
|
||||
else
|
||||
{
|
||||
ti->handler = nullptr;
|
||||
ti->hid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Timer::OnHandler(ushort num, void* param)
|
||||
{
|
||||
auto timer = (Timer*)param;
|
||||
if(timer)
|
||||
{
|
||||
timer->OnInterrupt();
|
||||
}
|
||||
}
|
|
@ -1,168 +0,0 @@
|
|||
#include "Device\WatchDog.h"
|
||||
|
||||
#include "RTL871x.h"
|
||||
|
||||
/*
|
||||
独立看门狗IWDG——有独立时钟(内部低速时钟LSI---40KHz),所以不受系统硬件影响的系统故障探测器。主要用于监视硬件错误。
|
||||
窗口看门狗WWDG——时钟与系统相同。如果系统时钟不走了,这个狗也就失去作用了,主要用于监视软件错误。
|
||||
|
||||
独立看门狗
|
||||
看门狗定时时限=IWDG_SetReload()的值 / 看门狗时钟频率
|
||||
看门狗时钟频率=LSI(内部低速时钟)的频率(40KHz)/ 分频数
|
||||
|
||||
独立看门狗(IWDG)由专用的40kHz的低速时钟为驱动。因此,即使主时钟发生故障它也仍然有效。
|
||||
窗口看门狗由从APB1时钟分频后得到的时钟驱动,通过可配置的时间窗口来检测应用程序非正常的过迟或过早的行为。
|
||||
IWDG_SetPrescaler() 分频,4~256
|
||||
IWDG_SetReload() 计数值12位 0~0x0FFF
|
||||
IWDG_ReloadCounter() 喂狗,必须在计数值减到1之前喂狗
|
||||
|
||||
IWDG_PR和IWDG_RLR寄存器具有写保护功能。要修改这两个寄存器的值,必须先向IWDG_KR寄存器中写入0x5555。
|
||||
以不同的值写入这个寄存器将会打乱操作顺序,寄存器将重新被保护。重装载操作(即写入0xAAAA)也会启动写保护功能。
|
||||
|
||||
#define IWDG_WriteAccess_Enable ((uint16_t)0x5555)
|
||||
#define IWDG_WriteAccess_Disable ((uint16_t)0x0000)
|
||||
|
||||
void IWDG_WriteAccessCmd(uint16_t IWDG_WriteAccess)
|
||||
{
|
||||
assert_param(IS_IWDG_WRITE_ACCESS(IWDG_WriteAccess));
|
||||
IWDG->KR = IWDG_WriteAccess;
|
||||
}
|
||||
|
||||
void IWDG_ReloadCounter(void)
|
||||
{
|
||||
IWDG->KR = KR_KEY_Reload;
|
||||
}
|
||||
void IWDG_Enable(void)
|
||||
{
|
||||
IWDG->KR = KR_KEY_Enable;
|
||||
}
|
||||
|
||||
void IWDG_SetPrescaler(uint8_t IWDG_Prescaler)
|
||||
{
|
||||
assert_param(IS_IWDG_PRESCALER(IWDG_Prescaler));
|
||||
IWDG->PR = IWDG_Prescaler;
|
||||
}
|
||||
void IWDG_SetReload(uint16_t Reload)
|
||||
{
|
||||
assert_param(IS_IWDG_RELOAD(Reload));
|
||||
IWDG->RLR = Reload;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
/*WatchDog::WatchDog(uint ms)
|
||||
{
|
||||
Timeout = ms;
|
||||
Config(ms);
|
||||
}*/
|
||||
|
||||
void OpenWatchDog()
|
||||
{
|
||||
RCC_LSICmd(ENABLE);
|
||||
/* 检查系统是否从IWDG重置恢复 */
|
||||
if (RCC_GetFlagStatus(RCC_FLAG_IWDGRST) != RESET)
|
||||
{
|
||||
/* 清除重置标识 */
|
||||
RCC_ClearFlag();
|
||||
}
|
||||
/* 打开IWDG_PR和IWDG_RLR寄存器的写访问 */
|
||||
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
|
||||
}
|
||||
|
||||
void SetWatchDog(byte pre, uint reload)
|
||||
{
|
||||
IWDG_SetPrescaler(pre);
|
||||
/*if(ms < (0x0FFF * 32 / 40))
|
||||
{
|
||||
// IWDG计数器时钟: LSI/32=40KHz/32=1250Hz,每周期0.8ms
|
||||
IWDG_SetPrescaler(IWDG_Prescaler_32);
|
||||
}
|
||||
else
|
||||
{
|
||||
// IWDG计数器时钟: LSI/64=40KHz/64=625Hz,每周期0.4ms
|
||||
IWDG_SetPrescaler(IWDG_Prescaler_64);
|
||||
|
||||
// 直接除以2,后面不用重复计算
|
||||
ms >>= 2;
|
||||
}*/
|
||||
|
||||
/* 设置计数器重载值为超时时间
|
||||
Counter Reload Value = ms / 1000 / IWDG计数器时钟周期
|
||||
= ms / 1000 / (1/(LSI/mul))
|
||||
= ms * LSI / (mul * 1000)
|
||||
= ms * 40k / (mul * 1000)
|
||||
= ms * 40 / mul
|
||||
*/
|
||||
IWDG_SetReload(reload);
|
||||
|
||||
/* 重载 IWDG 计数器 */
|
||||
IWDG_ReloadCounter();
|
||||
|
||||
/* 打开 IWDG (LSI将由硬件打开) */
|
||||
IWDG_Enable();
|
||||
}
|
||||
|
||||
bool WatchDog::Config(uint ms)
|
||||
{
|
||||
if(ms == 0)
|
||||
{
|
||||
debug_printf("WatchDog msTimeout %d 必须大于 0\r\n", ms);
|
||||
return false;
|
||||
}
|
||||
OpenWatchDog();
|
||||
|
||||
byte pre = IWDG_Prescaler_4;
|
||||
int mul = 4;
|
||||
// 计数器12位 0~0x0FFF,有reload = ms/1000 / (1/(LSI/mul)) = ms * LSI / (mul*1000) = ms * 40 / mul
|
||||
// 考虑到reload溢出的可能,每种分频最大ms = reload * mul / 40 ~= 102 * mul
|
||||
int i=0;
|
||||
/*
|
||||
#define IWDG_Prescaler_4 ((uint8_t)0x00)
|
||||
#define IWDG_Prescaler_8 ((uint8_t)0x01)
|
||||
#define IWDG_Prescaler_16 ((uint8_t)0x02)
|
||||
#define IWDG_Prescaler_32 ((uint8_t)0x03)
|
||||
#define IWDG_Prescaler_64 ((uint8_t)0x04)
|
||||
#define IWDG_Prescaler_128 ((uint8_t)0x05)
|
||||
#define IWDG_Prescaler_256 ((uint8_t)0x06)
|
||||
*/
|
||||
for(i = IWDG_Prescaler_4; i <= IWDG_Prescaler_256; i++)
|
||||
{
|
||||
pre = i;
|
||||
mul = 1 << (i + 2);
|
||||
|
||||
// 判断是否在范围之内
|
||||
if(ms * 40 / mul < 0x0FFF) break;
|
||||
}
|
||||
if(i > IWDG_Prescaler_256)
|
||||
{
|
||||
debug_printf("WatchDog msTimeout 必须小于 %d\r\n", 0x0FFF * 256 / 40);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* 设置计数器重载值为超时时间
|
||||
Counter Reload Value = ms / 1000 / IWDG计数器时钟周期
|
||||
= ms / 1000 / (1/(LSI/mul))
|
||||
= ms * LSI / (mul * 1000)
|
||||
= ms * 40k / (mul * 1000)
|
||||
= ms * 40 / mul
|
||||
*/
|
||||
SetWatchDog(pre, ms * 40 / mul);
|
||||
|
||||
Timeout = ms;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void WatchDog::ConfigMax()
|
||||
{
|
||||
OpenWatchDog();
|
||||
|
||||
SetWatchDog(IWDG_Prescaler_256, 0x0FFF);
|
||||
|
||||
Timeout = 0x0FFF * 256 / 40;
|
||||
}
|
||||
|
||||
void WatchDog::Feed()
|
||||
{
|
||||
IWDG_ReloadCounter();
|
||||
}
|
|
@ -10,6 +10,8 @@
|
|||
|
||||
const byte uart_irqs[] = UART_IRQs;
|
||||
|
||||
static void GetPins(byte index, byte remap, Pin* txPin, Pin* rxPin);
|
||||
|
||||
void SerialPort::OnInit()
|
||||
{
|
||||
_parity = USART_Parity_No;
|
||||
|
@ -22,6 +24,8 @@ bool SerialPort::OnSet()
|
|||
USART_TypeDef* const g_Uart_Ports[] = UARTS;
|
||||
assert_param(_index < ArrayLength(g_Uart_Ports));
|
||||
|
||||
GetPins(_index, Remap, &Pins[0], &Pins[1]);
|
||||
|
||||
auto sp = g_Uart_Ports[_index];
|
||||
_port = sp;
|
||||
|
||||
|
@ -32,12 +36,9 @@ bool SerialPort::OnSet()
|
|||
// 打开串口
|
||||
void SerialPort::OnOpen2()
|
||||
{
|
||||
Pin rx, tx;
|
||||
GetPins(&tx, &rx);
|
||||
|
||||
//串口引脚初始化
|
||||
_tx.Set(tx).Open();
|
||||
_rx.Init(rx, false).Open();
|
||||
// 串口引脚初始化
|
||||
if(!Ports[0]) Ports[0] = new Outport(Pins[0]);
|
||||
if(!Ports[1]) Ports[1] = new InputPort(Pins[1]);
|
||||
|
||||
auto st = (USART_TypeDef*)_port;
|
||||
|
||||
|
@ -224,7 +225,7 @@ void SerialPort::OnHandler(ushort num, void* param)
|
|||
#pragma arm section code
|
||||
|
||||
// 获取引脚
|
||||
void SerialPort::GetPins(Pin* txPin, Pin* rxPin)
|
||||
void GetPins(byte index, byte remap, Pin* txPin, Pin* rxPin)
|
||||
{
|
||||
*rxPin = *txPin = P0;
|
||||
|
||||
|
@ -232,10 +233,10 @@ void SerialPort::GetPins(Pin* txPin, Pin* rxPin)
|
|||
const Pin* p = g_Uart_Pins;
|
||||
#ifdef STM32F1
|
||||
const Pin g_Uart_Pins_Map[] = UART_PINS_FULLREMAP;
|
||||
if(Remap) p = g_Uart_Pins_Map;
|
||||
if(remap) p = g_Uart_Pins_Map;
|
||||
#endif
|
||||
|
||||
int n = _index << 2;
|
||||
int n = index << 2;
|
||||
*txPin = p[n];
|
||||
*rxPin = p[n + 1];
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue