【TC3xx芯片】TC3xx芯片STM介绍

目录

前言

正文

1. STM硬件资源

1.1 STM硬件单元

1.2 STM时钟

1.3 STM中断源

2. 功能描述

2.1 功能特色

2.2 STM计时器Timer

2.3 STM比较器功能

2.3.1 STM比较功能寄存器

2.3.2 STM比较器功能示例

2.3.3 STM比较器中断控制

2.4 配置STM是否在Debug时停止

3. AUTOSAR OS中的配置

3.1 OsHardwareTimerChannels

3.2 OsIsrs中配置STM中断

3.3 OsCounters引用STM Timer

4. 总结


前言

基于Aurix芯片的Davinci工具链的MICROSAR OS的系统Counter(系统心跳)使用的硬件时钟STM(System Timer),在学习OS前有必要了解下Aurix芯片的STM模块。本文就来详细介绍下Aurix芯片的STM模块。

缩略词

简写

全称

STM

System Timer

CMCON

Compare Match Control Register

参考文档:

1. TriCoreTM TC1.6.2 core architecture manual

2. AURIXTC3XX_um_part1_v2.0.pdf

3. TC37x_appx_um_v2.0.pdf

正文

1. STM硬件资源

1.1 STM硬件单元

TC37x芯片有3个STM模块,每个STM模块可以产生两个SRx_INT中断信号(通过STM模块的Compare功能实现,下文介绍),Davinci OS中的硬件定时器就是使用STM模块的SRx_INT中断信号

1.2 STM时钟

系统冷启动或者系统复位后,fSTM=50MHz,也就是fSTM的一个tick为1/(50*(10^6)) = 0.00000002 s = 20ns.

Note: TC37x的时钟系统后面的文章再介绍,本文默认系统启动后fSTM就为50MHz.

1.3 STM中断源

在1.1章节中介绍了TC37x有3个STM硬件单元,每个STM硬件单元可以产生两个中断信号,中断号计算公式如下截图所示:

e.g. STM0的SR0_INT = 0x300 + 0*8 + 0*4 = 0x300 = 768.

2. 功能描述

2.1 功能特色

. 一个不受约束的64-bit计数器,也就是能产生一个0 – 2^64的计数,如果我们使用fSTM = 50MHz,那么计数器的最大计数值对应的最大时间为:2^64 * 20ns = 4270079.647..天 = 11698 年,也就说实际使用中这个计数器不可能溢出。

. 这个64b-bit计数器可以同步读出。理论上,TC37x是32-bit系统,每个指令周期顶多能读32-bit数据,TC37x芯片是怎么保证64-bit计时器值同步读出来的了? -- 通过STM_CAP寄存器机制,后面介绍。

64 位计数器的不同 32 位部分可以同步读取。STM的64-bit提供了6个32-bit Timer可以同步读出来,后文介绍。

. 基于与部分 STM 内容的比较匹配,灵活地生成服务请求。通过STM_CMPx的比较机制灵活的产生服务请求事件,后文具体介绍。

. 系统启动后,STM自动启动

. 如果ARSTDIS.STMxDIS被清除,则Application Reset也会Reset STM registers;如果ARSTDIS.STMxDIS没有被清除,则Application Reset不会Reset STM registers,只有System Reset才会Reset STM registers.

2.2 STM计时器Timer

STM作为Timer时,可以提供7个不同基准的Timer:

STM_TIM0: 基准为2^0 tick = 1 tick = 20 ns,也就是每20 ns,计数器加1.

STM_TIM1: 基准为2^4 tick = 16 tick = 320 ns,…

STM_TIM2: 基准为2^8 tick = 256 tick = 5120 ns = 5.120 us,…

STM_TIM3: 基准为2^12 tick = 4096 tick = 81920 ns = 81.92 us,…

STM_TIM4: 基准为2^16 tick = 65536 tick = 1310720 ns = 1.31072 ms,…

STM_TIM5: 基准为2^20 tick = 1048576 tick = 209715220 ns = 0. 20971522 s,…

STM_TIM6: 基准为2^32 tick = 4294967296 tick = 85899345920 ns = 85.899345920 s,…

理论上,TC37x是32-bit系统,每个指令周期顶多能读32-bit数据且在读取32-bit数据的时候STM是不会停下来等你再读另一个32-bit的数据的,TC37x芯片是怎么保证64-bit计时器值同步读出来的了? -- 通过STM_CAP寄存器机制,每次读取其中一个寄存器 TIM0 至 TIM5 时,它都会锁定 STM 高部分的内容。 因此,在读取下部时, CAP 完全同时保存计时器的上限值。 然后,第二个读取操作将读取 CAP 的内容以获得完整的计时器值。

2.3 STM比较器功能

64 位系统计时器的内容可以与 CMP0 和 CMP1 寄存器中存储的两个比较值的内容进行比较。 服务请求可以在 STM 与 CMP0 或 CMP1 寄存器的比较匹配上生成。

2.3.1 STM比较功能寄存器

CMCON(Compare Match Control Register)寄存器的MSIZEx位域配置CMPx寄存器从0-bit开始多少位用来和STM比较,MSTARTx位域配置STM Counter的哪一位开始和CMPx寄存器比较。

2.3.2 STM比较器功能示例

如下图所示,对应的CMCOM的配置为:

. MSIZE0 = 10001B = 17D; MSTART0 = 01010B = 10D

. MSIZE1 = 00111B = 7D; MSTART1 = 00111B = 7D

MSIZE0 = 10001B = 17D : Compare Register0从0-bit开始的7个bit用于比较

MSTART0 = 01010B = 10D : 和STM的第10-bit位开始的7个bit比较

CMP1类似……

Compare成功后,就会产生Event,Event可用于配置中断。

2.3.3 STM比较器中断控制

Compare中断事件产生举例:

第1步:配置STMx_CMCON. MSTARTx位域,设置比较寄存器在STM中的起始位置。

第2步:配置STMx_CMCON.MSIZEx使用STM_CMPx的宽度(多少bit)。

第3步:配置STM_CMPx. CMPVAL[31:0]定时器值。

第4步:配置STM_ICR.CMPxOS到时触发STMIR0还是STMIR1中断。

第5步:配置STM_ICR.CMPxEN使能中断,等待定时中断触发。

中断触发后:在中断服务例程(ISR,中断服务函数)里设置STM_ISCR.CMPxIRR=1清除中断,并重复上述第5步操作重新使能中断,等待中断触发。

2.4 配置STM是否在Debug时停止

OCS. SUS[27:24]位域配置为0时,STM计时不会被外部调试器的操作打断;  OCS. SUS[27:24]位域配置为2, 在使用调试器Stop程序的时候,STM会同步Stop计时。

3. AUTOSAR OS中的配置

3.1 OsHardwareTimerChannels

Davinci的SIP包中硬件相关的配置都是默认配置好,TC37x芯片有三个STM定时器,每个STM有两个通道(也就每个STM能产生两个中断事件)。

3.2 OsIsrs中配置STM中断

OsIsrs中关于STM产生的中断也是默认配置好的,使用三个STM的Channel0通道。

3.3 OsCounters引用STM Timer

OsCounsters使用硬件定时器STM,需要引用STM的配置。

4. 总结

STM一般用作Os的Timer,如果OS中配置使用了STM,那么应用就不能再使用了。具体怎么使用,那就是Os的静态代码实现的了。作为学习,我们理解了STM的Compare Operation机制就能去阅读Os是怎么配置寄存器实现Timer功能的了。

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是基于Keil5和STM32F407VE芯片利用ESP8266模块连接知心天气获取天气信息的代码: ```c #include "stm32f4xx.h" #include <stdio.h> #include <string.h> #define SSID "Your_SSID" // 请替换成自己的WiFi名称 #define PASSWORD "Your_Password" // 请替换成自己的WiFi密码 void USART3_Configuration(void); void USART3_SendChar(uint16_t Data); void USART3_SendString(char *str); void ESP8266_Configuration(void); void ESP8266_SendCommand(char *cmd); char ESP8266_ReceiveChar(void); void ESP8266_ReceiveResponse(char *response); void ESP8266_ClearBuffer(void); void Delay_ms(uint32_t nCount); int main(void) { char response[200]; char cmd[100]; char temp[10], weather[20]; // 存放温度和天气 uint8_t i; RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); USART3_Configuration(); ESP8266_Configuration(); // 连接WiFi sprintf(cmd, "AT+CWJAP=\"%s\",\"%s\"\r\n", SSID, PASSWORD); ESP8266_SendCommand(cmd); ESP8266_ClearBuffer(); // 获取天气信息 ESP8266_SendCommand("AT+CIPSTART=\"TCP\",\"www.zxweather.com\",80\r\n"); ESP8266_ClearBuffer(); Delay_ms(1000); sprintf(cmd, "GET /WeatherAPI/weather.aspx?city=beijing HTTP/1.1\r\nHost: www.zxweather.com\r\n\r\n"); sprintf(temp, "Content-Length: %d\r\n", strlen(cmd)); sprintf(cmd, "AT+CIPSEND=%d\r\n", strlen(cmd) + strlen(temp) + 2); ESP8266_SendCommand(cmd); ESP8266_ClearBuffer(); Delay_ms(1000); ESP8266_SendCommand(temp); ESP8266_SendString(cmd); ESP8266_SendString("\r\n"); ESP8266_ClearBuffer(); Delay_ms(1000); ESP8266_ReceiveResponse(response); for (i = 0; i < strlen(response); i++) { if (response[i] == '\"') { i++; break; } } strncpy(temp, response + i, 4); // 获取温度 temp[4] = '\0'; strncpy(weather, response + i + 6, 8); // 获取天气 weather[8] = '\0'; USART3_SendString("Temperature: "); USART3_SendString(temp); USART3_SendString("\r\n"); USART3_SendString("Weather: "); USART3_SendString(weather); USART3_SendString("\r\n"); while (1); } void USART3_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_USART3); GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_USART3); USART_InitStructure.USART_BaudRate = 9600; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_Init(USART3, &USART_InitStructure); USART_Cmd(USART3, ENABLE); } void USART3_SendChar(uint16_t Data) { while (USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET); USART_SendData(USART3, (uint8_t)Data); } void USART3_SendString(char *str) { while (*str) { USART3_SendChar(*str++); } } void ESP8266_Configuration(void) { char response[100]; ESP8266_SendCommand("AT+RST\r\n"); ESP8266_ClearBuffer(); Delay_ms(3000); ESP8266_SendCommand("AT+CWMODE=1\r\n"); ESP8266_ClearBuffer(); ESP8266_SendCommand("AT+CIPMUX=0\r\n"); ESP8266_ClearBuffer(); } void ESP8266_SendCommand(char *cmd) { while (*cmd) { USART3_SendChar(*cmd++); } } char ESP8266_ReceiveChar(void) { while (USART_GetFlagStatus(USART3, USART_FLAG_RXNE) == RESET); return (char)USART_ReceiveData(USART3); } void ESP8266_ReceiveResponse(char *response) { uint8_t i = 0; char c; while (i < 200) { c = ESP8266_ReceiveChar(); response[i++] = c; if (c == '\n') { break; } } response[i] = '\0'; } void ESP8266_ClearBuffer(void) { char c; while (USART_GetFlagStatus(USART3, USART_FLAG_RXNE) == SET) { c = USART_ReceiveData(USART3); } } void Delay_ms(uint32_t nCount) { uint32_t i, j; for (i = 0; i < nCount; i++) { for (j = 0; j < 2000; j++); } } ``` 注意:在使用该代码之前,请先在ESP8266模块上烧录AT固件。并且请替换代码中的WiFi名称和密码为自己的WiFi名称和密码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

汽车电子嵌入式

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值