重构串口驱动输入输出引脚,便于移植

This commit is contained in:
大石头X2 2016-12-27 18:51:26 +08:00
parent bf7743b3cc
commit 365bb2a26e
20 changed files with 29 additions and 2246 deletions

View File

@ -12,7 +12,7 @@ Pwm::Pwm(TIMER index) : Timer(index)
Enabled[i] = false;
}
Remap = 0;
//Remap = 0;
}
Pwm::~Pwm()

View File

@ -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]; // 每个通道是否启用

View File

@ -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();

View File

@ -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();

View File

@ -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];
}

View File

@ -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) { }
}
}
}

View File

@ -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");

View File

@ -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
}

View File

@ -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线的时钟信号是低电平时才能改变
*/

View File

@ -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();
}

View File

@ -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
}

View File

@ -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();
}

View File

@ -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

View File

@ -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位
1USART_SR寄存器
2USART_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;
}
}

View File

@ -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
}

View File

@ -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); }

View File

@ -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;
}

View File

@ -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();
}
}

View File

@ -1,168 +0,0 @@
#include "Device\WatchDog.h"
#include "RTL871x.h"
/*
IWDGLSI---40KHz 
WWDG 
=IWDG_SetReload() /
=LSI40KHz/ 
(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();
}

View File

@ -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];
}