嵌入式系統

advertisement
嵌入式系統 training
- HT32F175x275x
袁世一
逢甲通訊系
1
Outline
•
•
•
•
•
•
Embedded system vs. …
Clock Control
GPIO – General purpose I/O
Counter
Interrupt
AFIO – Alternate Function I/O
2
Embedded system vs. …
PC
Embedded
Single chip
Purpose
General Purpose
Special
Special
SoC
No
Yes
Yes
IO Functions
Easy
Complicated
Easy
Program type
Complicated
Complicated
Easy
IO programming
Easy
Complicated
Easy
Memory
External
Internal/External
Internal/External
Internal Memory size
Generally 0
~ Kbyte
~ 100 Byte
Block Func
Less / Fast
More / Medium
Less / Slow
So, programming in Embedded system different from …
• care about special purposes
• care about memory
• care about HW considerations
• care about COST
3
上課預計時程
日期
上午(0900-1200)
下午(1300-1600)
備註
7/1
Clock, GPIO教學
程式練習
GPIO設定與
Clock設定有關,
必須同時練習
7/2
Counter教學、
程式練習
中斷教學、
程式練習
以不同Counter程式設
計方式(迴圈, 中斷)
做為練習目標
7/3
AFIO+中斷教學
程式練習
王磊老師上課,
下午時間需要確認
AFIO將以ADC為例
作為練習目標
*希望7/1進度可以提前,以增加7/3的程式說明時間
4
Clock control (7/1)
• 基礎 ARM 時脈概念
• HT32F125x 時脈控制單元 (clock control unit,
CKCU)
• 範例程式
5
General ARM clock concept
• 時脈是控制嵌入式系統動作同步的訊號
• ARM為: 系統晶片SoC (System on Chip)
– 許多功能區塊整合在IC內部
• 連在不同的Bus (匯流排)上,以提升IC效能
• 不同Bus可以使用不同的時脈
– Bus種類: 高/低速bus
• AHB: High speed bus
• APB: Low speed (Peripheral) bus
6
7
ARM 時脈種類
1.
HSI & LSI – High/Low speed Internal RC oscillator
–
HSI:
•
•
•
–
LSI:
•
•
•
•
2.
系統預設時鐘,內部RC振盪
可以直接作為系統時鐘或作為PLL輸入(PLL=HSI/2)
精度較差
內部RC振盪
低功耗時脈源
可以在停機和待機模式下保持系統運做
提供看門狗和自動喚醒單元時脈
HSE & LSE – High/Low speed External crystal
–
HSE:外部振盪器
•
–
提供非常精確的主時鐘
LSE:低速外部晶體
•
一般專門用於RTC
8
9
10
3. PLL – phase lock loop
(倍頻/除頻)
•
•
prescalers/multiplexers
(倍頻/除頻設定)
System clock (CK_SYS)
-> AHB/APB
4. gating (停止某些電路
功能)
11
Clk setup: 以PLL設定為例
12
CKCU Registers 設定舉例
• Global Clock
Configuration Register
(GCFGR)
– 32 bits
– specifies clock source for
PLL/USART/Watchdog
Timer/CKOUT circuits
• 使用C即可
• 如需深入了解,請見
SPEC中Registers說明
CKCU_APBPerip0ClockConfig(CKCU_APBEN0_AFIO,
ENABLE);
CKCU_APBPerip0ClockConfig(BUTTON_GPIO_PIN,
ENABLE);
13
GPIO – General purpose I/O (7/1)
• ARM GPIO 架構
• ARM IO 控制
14
15
ARM GPIO architecture
• 32個GPIO Pin
– PA0~PA15 / PB0~PB15
– 其他功能腳位也可以分享GPIO port來增加功能
的彈性
– 透過相關的組態暫存器的設定
16
GPIO控制
• 方向:輸入 OR 輸出
• 輸入腳位控制
– 弱拉升/弱拉降
• 輸出腳位控制
– 推拉式控制 OR 開汲極
– 推動電流強度
– 類比/數位 (AFIO控制) – 之後會說明
• 組態鎖定
17
RESET(或初供電)時GPIO之預設值
– 均為input
• 無拉升/拉降電阻 (no pull-up/pull-down)
– 例外:
• PA9(拉降)、PA10 (拉升) 、PA13 (拉升) 、PA14 (拉升)
• For boot/debug
18
GPIO Registers設定舉例
• Port A Data Direction
Control Register
(PADIRCR)
– 32 bits
– control the direction of
the GPIO Port
• 同時脈設定,使用C即
可
• 如需深入了解,請見
SPEC中Registers說明
GPIO_DirectionConfig(KEY1_BUTTON_GPIO_PORT,
KEY1_BUTTON_GPIO_PIN, GPIO_DIR_IN);
GPIO_DirectionConfig(LED1_GPIO_PORT,
LED1_GPIO_PIN, GPIO_DIR_OUT);
19
程式範例
int main(void)
{
system_init();
while(1) {
x = read_input_pin;
write_output(x);
}
while(1)
}
{
TmpStatus = GPIO_ReadInBit(WAKEUP_BUTTON_GPIO_PORT, WAKEUP_BUTTON_GPIO_PIN);
GPIO_WriteOutBits(LED1_GPIO_PORT, LED1_GPIO_PIN, TmpStatus);
TmpStatus = GPIO_ReadInBit(KEY1_BUTTON_GPIO_PORT, KEY1_BUTTON_GPIO_PIN);
GPIO_WriteOutBits(LED2_GPIO_PORT, LED2_GPIO_PIN, TmpStatus);
TmpStatus = GPIO_ReadInBit(KEY2_BUTTON_GPIO_PORT, KEY2_BUTTON_GPIO_PIN);
GPIO_WriteOutBits(LED3_GPIO_PORT, LED3_GPIO_PIN, TmpStatus);
}
}
20
程式範例
• system_init:
– Enable APB clock
1.
2.
3.
4.
5.
enable APB clock for 3
pins
connect 3 pins to GPIO
function (Port, Pin, Func)
3 pins’ GPIO as Input
enable 3 pins
same as 1-4 for 3 output
pins
• loop
– x=read input
– output x -> y
int main(void)
{
…
CKCU_APBPerip0ClockConfig(CKCU_APBEN0_AFIO, ENABLE);
CKCU_APBPerip0ClockConfig(DVB_GpioClock[WAKEUP_BUTTON_G
PIO_ID], ENABLE);
…
HT32F_DVB_GPxConfig(WAKEUP_BUTTON_GPIO_ID,
WAKEUP_BUTTON_AFIO_PIN, WAKEUP_BUTTON_AFIO_MODE);
…
GPIO_DirectionConfig(WAKEUP_BUTTON_GPIO_PORT,
WAKEUP_BUTTON_GPIO_PIN, GPIO_DIR_IN);
…
GPIO_InputConfig(WAKEUP_BUTTON_GPIO_PORT,
WAKEUP_BUTTON_GPIO_PIN, ENABLE);
…
//5: 3 output pins
…
• Too many codes
– see code example
while(1)
{
…
}
}
21
Practice
• Target
1. 使用for, 控制LED閃爍
2. 讀取按鈕值, 控制LED閃爍
•
按一次亮, 再一次暗
3. 讀取按鈕值, 控制LED閃爍的開始/停止
•
按一次開始閃爍, 再一次停止閃爍
22
Counter (計數器) (7/2)
• HT32Fx has 4 counters:
– GPTM0/1: General Purpose Timer 0 & 1
– BFTM0/1: Basic Function Timer 0 & 1
23
Counter
• This training uses
BFTM0
• Two method:
1. loop method – this
training
2. Interrupt method –
next training
• BFTM需要設定:
– Counter Reg: up counter
– Compare Reg: max value
– Status Reg:
Counter==Compare
• Use C-lib
24
Counter loop programming
1. clock Init, LED(GPIO)
Init
2. BFTM setting
1.
max value
–
–
2.
3.
sysCLK: 1sec
sysCLK/2: 0.5sec
counter value (=0)
BFTM as OneShot
int main(void)
{
CKCU_APBPerip1ClockConfig(…);
HT32F_DVB_LEDInit(LED2);
BFTM_SetCompare(BFTM1, SystemCoreClock);
BFTM_SetCounter(BFTM1, 0);
BFTM_OneShotModeCmd(BFTM1, ENABLE);
while (1)
{
BFTM_EnaCmd(BFTM1, ENABLE);
3. loop(1)
1.
2.
3.
start BFTM (enable)
wait for BFTM.status
change
toggle LED
while (BFTM_GetFlagStatus(BFTM1) != SET);
BFTM_ClearFlag(BFTM1);
HT32F_DVB_LEDToggle(LED2);
}
}
25
Counter programming
• Interrupt counter control:
– Training latter
26
Interrupt (7/2)
• Interrupt concept
• ARM NVIC
• sample code
27
Interrupt concept
• 中斷是一個訊號,會促使電
腦改變其正常的運作流程。
• 在接收到來自外部硬體信號
之後,CPU將進行相應的硬
/軟體處理
– 發出的信號稱為中斷請求
(interrupt request,IRQ)
– IRQ導致CPU執行資訊切換
(context switch)來保存執行
狀態
– 中斷會將控制權轉換到中斷
處理常式(Interrupt Service
Routine, ISR)
• 軟體中斷則為CPU指令集中
的一個中斷指令
28
29
• 種類
– 狀態觸發
– 邊沿觸發
• 中斷向量表
– 中斷向量表包含數個中
斷向量,每個向量包含
中斷處理程序的起始地
址
30
• 中斷處理過程
– 外部硬體信號發出IRQ
– CPU結束執行上一個機械
碼
– CPU同意中斷
– CPU儲存CPU執行狀態
– CPU取得中斷位址
– CPU執行ISR
– ISR執行完成
– CPU取得中斷前CPU執行
狀態
– CPU繼續執行原本程式
31
ARM NVIC
• NVIC – Nested Vectored
Interrupt Controller
• Interrupt Number: 31
peripheral Int
NVIC_EnableIRQ(BFTM0_IRQn);
• Interrupt Types:
–
–
–
–
–
USART, SPI, I2C
Timer (BFTM, GPTM)
ADC, Comparator,
GPIO input
WakeUP signal, RTC, Low
Vdd
– Clock (HSE, HIS, LSE, LSI,
PLL)
• Priority: configurable,
16 levels
32
Counter Interrupt programming
1. clock Init, LED(GPIO)
Init
2. BFTM_INT unmask
3. BFTM setting
1.
2.
3.
4.
int main(void)
{
CKCU_APBPerip1ClockConfig(…);
HT32F_DVB_LEDInit(LED1);
NVIC_EnableIRQ(BFTM0_IRQn);
max value
BFTM_SetCompare(BFTM0, SystemCoreClock/2);
BFTM_SetCounter(BFTM0, 0);
BFTM_IntConfig(BFTM0, ENABLE);
BFTM_EnaCmd(BFTM0, ENABLE);
–
–
while (1) { }
}
sysCLK: 1sec
sysCLK/2: 0.5sec
counter value (=0)
BFTM Interrupt enable
begin BFTM
4. loop(1) do_nothing();
//in ht32f…_it.c:
// Interrupt service routing (ISR):
void BFTM0_IRQHandler(void)
{
HT32F_DVB_LEDToggle(LED1);
BFTM_ClearFlag(BFTM0);
}
33
AFIO – Alternate Function I/O (7/3)
•
•
•
•
擴大GPIO 的靈活性
GPIO外設功能
每個GPIO腳
配置為有四個不同的功能(設置GPxCFGR 暫
存器)
• 根據IP 資源的使用情況和應用需求,可以
使用週邊I/O 映射機制來選擇合適的功能
34
35
AFIO 功能
36
AFIO 功能
37
Example: ADC
• Set AFIO to ADC
• Set ADC to get Analog
data from
potentionmeter (電位
計)
38
HT32F ADC 特性
•
•
•
•
12-bit ADC
Sample rate: Up to 1 uS/S
8 external channels
2 int_ref_voltage:Vssa &
Vdda
• sampling time for each
channel
• Three conversion modes
– One shot
– Continuous
– Discontinuous
• 8 dedicated sequencers
and data registers
• Triggered by
– Software
– external interrupt
– GPTM (MTO and PWM
CHnO)
• Interrupts for ...
–
–
–
–
–
Single conversion end
Subgroup conversion end
Cycle conversion end
Analog Watchdog
Data register overwrite
39
• Function descriptions
Configuration
– ADRST [0] = 1: ADC reset
• Clock setup:
– CK_ADC = APB_PCLK
• ADC Trigger
– ADCTCR (Trigger Control
Registers)
• ADTM = ADCTCR[2]: GPTM
enable
• ADEXTI = ADCTCR[1]: EXTI
enable
• ADSW = ADCTCR[2]: SW
enable
– ADCTSR (Trigger Source
Registers)
• GPTME = ADCTSR[26:24]:
GPTM Event selection (all at
rising edge_
– 0: GPTM MTO
– 1-4: CH0-CH3
• GPTMS = ADCTSR[18:16]
GPTM selection
– 2/3 = GPTM0/GPTM1
• ADEXTIS = ADCTSR[11:8] : EXTI
line selection
– 0-F: EXTI line 0-15
• ADSC = ADCSTR[0]:
– set: SW Event begin once
– reset: automatic when this
ADC complet
40
• Data save register
• ADCDRn (n=0-7)
• flag ADVLDn goes to
1, automatically , if ADCDRn
is valid
• flag ADVLDn goes to
0, automatically, if ADCDRn
is read
• if ADCDRn not read and
overwrited by another ADC
round, ADIAWO of
ADCIRAW = 1
• Status Flags
• ADIRAWO =
ADCIRAW[24]: data register
overwrite error
• ADIRAWS =
ADCIRAW[2]: register: single
sample finish
• ADIRAWG =
ADCIRAW[1]: register: subgroup finish
• ADIRAWC =
ADCIRAW[0]: register: cycle
(group) finish
41
• Interrupt
• ADIMASKO = ADCIMSK[24]:
ADC Data overwrite INT
mask
• ADIMASKC = ADCIMSK[2]:
cycle (group) finish INT
mask
• ADIMASKG = ADCIMSK[1]:
sub-group finish INT mask
• ADIMASKS = ADCIMSK[0]:
single ADC finish INT mask
• Trigger begin:
• SW trigger: ADSC of ADCTSR
(when start ADC, ADSC
reset)
• 5 GPTM trigger: MTO
(master), 4 GPTM-CHn (n=03)
• EXTInt trigger:
– setup: ADEXIS register EXTInt (n=0,1)
– ADEXTI=1
42
• Sample time:
• ADSTn of
ADCSTRn[7:0] (n=0-7):
– sampling time of channel n
– T_conv = Tsample + Tlat
– (conversion time, sampling
time, latency)
– Tasmple = ADSTn + 1.5
cycle
– minimum Tlat = 12.5 cycle
• Example:
– CK_ADC = 14MHz, ADSTn =
0
– Tconv = 1.5 + 12.5 = 14
cycles (=1us)
43
• Turn off ADC: ADCEN reset
• Interrupt setup
• All flags are set by SW for
clearing, and automatically
reset by HW
• ADCICLRO = ADCICLR[24]: ADC
Data overwrite INT Clear
• ADCICLRC = ADCICLR[2]: cycle
(group) finish INT clear
• ADCICLRG = ADCICLR[1]: subgroup finish INT mask clear
• ADCICLRS = ADCICLR[0]: single
ADC finish INT mask clear
44
Sample Code
int main(void)
{
USART_Configuration(); //for PC
Enable_ADC_IRQ();
ADC_Clock_Enable();
AFIO_PIN6_SetTo_ADC();
ADC_Configure(ContinuousMode, 1 channel, sample rate, SW_trigger);
ADC_enable();
begin_ADC();
while (1)
{
/* Output gPotentiometerLevel if needed. */
printf("\rPotentiometer level is %d %% ", (int)gPotentiometerLevel);
}
}
45
USART_Configuration
void USART_Configuration(void)
{
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 115200;
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_NORMAL;
HT32F_DVB_COMInit(COM1, &USART_InitStructure);
}
46
Enable_ADC_IRQ
NVIC_EnableIRQ(ADC_IRQn);
47
ADC_Clock_Enable
/* Enable peripheral clock of ADC */
CKCU_APBPerip1ClockConfig(CKCU_APBEN1_ADC, ENABLE);
CKCU_APBPerip0ClockConfig(CKCU_APBEN0_AFIO, ENABLE);
/* ADCLK frequency is set to 72/64 MHz = 1.125MHz */
CKCU_SetADCPrescaler(CKCU_PCLK_DIV64);
48
AFIO_PIN6_SetTo_ADC
/* Config AFIO mode as ADC function */
AFIO_GPAConfig(AFIO_PIN_6 , AFIO_MODE_1);
49
ADC_Configure
/* Continuous Mode, Length 1, SubLength 1 */
ADC_RegularGroupConfig(ADC, CONTINUOUS_MODE, 1, 1);
/* ADC Channel 6, Rank 0, Sampling clock is (1.5 + 0) ADCLK
Conversion time = (sampling clock + 12.5) / ADCLK = 12.4 uS */
ADC_RegularChannelConfig(ADC, ADC_CH_6, 0, 0);
/* Use Software Trigger as ADC trigger source */
ADC_RegularTrigConfig(ADC, ADC_TRIG_SOFTWARE);
50
ADC_enable()
/* Enable ADC single end of conversion interrupt,
The ADC ISR will store the ADC result into global variable
gPotentiometerLevel. */
ADC_IntConfig(ADC,ADC_INT_SINGLE_EOC, ENABLE);
//in: ht32f175x_275x_it.c
void ADC_IRQHandler(void)
{
ADC_ClearIntPendingBit(ADC, ADC_FLAG_SINGLE_EOC);
gPotentiometerLevel = (((ADC->DR[0]&0x0FFF)*100)/4095);
}
51
begin_ADC
/* Software trigger to start continuous mode */
ADC_SoftwareStartConvCmd(ADC, ENABLE);
52
Sample Code
int main(void)
{
USART_Configuration();
Enable_ADC_IRQ();
ADC_Clock_Enable();
AFIO_PIN6_SetTo_ADC();
ADC_Configure(ContinuousMode, 1 channel, sample rate, SW_trigger);
ADC_enable();
begin_ADC();
while (1)
{
/* Output gPotentiometerLevel if needed. */
printf("\rPotentiometer level is %d %% ", (int)gPotentiometerLevel);
}
}
53
Sample Code
int main(void)
{
USART_Configuration();
NVIC_EnableIRQ(ADC_IRQn);
CKCU_APBPerip1ClockConfig(CKCU_APBEN1_ADC, ENABLE);
CKCU_APBPerip0ClockConfig(CKCU_APBEN0_AFIO, ENABLE);
CKCU_SetADCPrescaler(CKCU_PCLK_DIV64);
AFIO_GPAConfig(AFIO_PIN_6 , AFIO_MODE_1);
ADC_RegularGroupConfig(ADC, CONTINUOUS_MODE, 1, 1);
Conversion time = (sampling clock + 12.5) / ADCLK = 12.4 uS */
ADC_RegularChannelConfig(ADC, ADC_CH_6, 0, 0);
ADC_RegularTrigConfig(ADC, ADC_TRIG_SOFTWARE);
ADC_IntConfig(ADC,ADC_INT_SINGLE_EOC, ENABLE);
ADC_SoftwareStartConvCmd(ADC, ENABLE);
while (1) {
printf("\rPotentiometer level is %d %% ", (int)gPotentiometerLevel);
}
}
54
Practice
Target 1 (first practice)
1. read sample code –
knowing each line’s
meaning
2. connect the behavior
in mind
3. compiling/executing
code
Target 2 (second practice)
1. change PC’s ADC value
to binary
2. check the stability of
ADC
3. change ADC channel to
2 if possible
Note: 下午是王壘老師上課,下午上課時間
需要確認
55
Download