惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V2EX - 技术
V2EX - 技术
T
Troy Hunt's Blog
The Last Watchdog
The Last Watchdog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
S
Secure Thoughts
Hacker News - Newest:
Hacker News - Newest: "LLM"
WordPress大学
WordPress大学
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 司徒正美
TaoSecurity Blog
TaoSecurity Blog
博客园 - Franky
有赞技术团队
有赞技术团队
Google Online Security Blog
Google Online Security Blog
罗磊的独立博客
L
LINUX DO - 最新话题
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
NISL@THU
NISL@THU
小众软件
小众软件
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Recent Commits to openclaw:main
Recent Commits to openclaw:main
K
Kaspersky official blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
W
WeLiveSecurity
SecWiki News
SecWiki News
Google DeepMind News
Google DeepMind News
O
OpenAI News
V
V2EX
AI
AI
博客园_首页
Apple Machine Learning Research
Apple Machine Learning Research
大猫的无限游戏
大猫的无限游戏
美团技术团队
C
Cyber Attacks, Cyber Crime and Cyber Security
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Security Archives - TechRepublic
Security Archives - TechRepublic
博客园 - 三生石上(FineUI控件)
G
GRAHAM CLULEY
月光博客
月光博客
T
Threatpost
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
V
Vulnerabilities – Threatpost
Last Week in AI
Last Week in AI
爱范儿
爱范儿
C
CXSECURITY Database RSS Feed - CXSecurity.com
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Cloudbric
Cloudbric
酷 壳 – CoolShell
酷 壳 – CoolShell
The Hacker News
The Hacker News
N
News | PayPal Newsroom
Know Your Adversary
Know Your Adversary

博客园 - 真 OO无双

(轉貼) Bit Twiddling Hacks (SOC) (Verilog) (C) (筆記) 如何移除VirtualBox所遺留下的驅動程式? (SOC) (VirtualBox) (筆記) always block內省略else所代表的電路 (SOC) (Verilog) (原創) Qsys或RTL做修改後,Nios II SBT該如何面對新的硬體? (SOC) (Nios II) (Qsys) (原創) 如何解決目錄改變時,Nios II project無法編譯的問題? (SOC) (Nios II) (DE2-70) (原創) Qsys Generation Tab的Simulation設定的意義 (SOC) (Nios II) (Qsys) (筆記) 如何寫入binary file某個byte連續n byte的值? (C/C++) (C) (筆記) 如何寫入binary file某個byte的值? (C/C++) (C) (筆記) 如何讀取binary file某個byte連續n byte的值? (C/C++) (C) (筆記) 如何讀取binary file某個byte的值? (C/C++) (C) (原創) Altera Technology Roadshow 2011 Taipei (SOC) (Quartus II) (Nios II) (Qsys) (原創) 如何在安裝SELinux的環境執行Quartus II? (SOC) (Quartus II) (Linux) (RedHat) (筆記) 如何得知Quartus II最新版到底修改了哪些東西? (SOC) (Quartus II) (Nios II) (SOPC Builder) (Qsys) (筆記) Qsys resource整理 (SOC) (Nios II) (Qsys) (原創) 如何安裝Linux版本的Quartus II? (SOC) (Quartus II) (Linux) (RedHat) (VirtualBox) (筆記) 如何在RedHat Linux安裝VirtualBox Guest Additions? (SOC) (Linux) (RedHat) (VirtualBox) (筆記) 常用設定暫存器值的編程技巧 (SOC) (C/C++) (C) (Verilog) (原創) Quartus II安裝新觀念:如何將Quartus II安裝在VirtualBox內? (SOC) (Quartus II) (VirtualBox) (筆記) $dispaly()、$strobe()、$monitor() 、$fwrite()與blocking / nonblocking的關係 (SOC) (Verilog) (Debussy) (Verdi)
(原創) 如何在Qsys Subsystem使用Interrupt? (SOC) (Nios II) (Qsys)
真 OO无双 · 2012-01-04 · via 博客园 - 真 OO无双

Abstract
Qsys其中之一的賣點就是允許你建立hierarchical的subsystem。在SOC設計中,通常我們會將慢速的周邊使用較慢的clock而自成一個系統,在Qsys中允許我們將這些較慢的周邊包成一個peripheral subsystem,而不是像SOPC Builder一樣只能有一個system。當我們使用subsystem的架構時,該如何讓subsystem內IP使用interrupt的方式與Nios II溝通呢?

Introduction
使用環境:Windows XP SP3 + VirtualBox 4.1.2 + Quartus II 11.0

本文將討論以下主題:

1.如何使用IRQ Bridge連接subsystem的IRQ export到Nios II Processor?

2.如何避開Nios II SBT目前無法自動產生IRQ number常數在system.h的bug?

3.如何在App project使用Interrupt?

1.如何使用IRQ Bridge連接subsystem的IRQ export到Nios II Processor?

根據[1] Qsys Interconnect p.7-27 IRQ Bridge章節的建議,若要在subsystem使用interrupt,必須在包含Nios II的CPU subsystem使用IRQ Bridge接收Peripheral subsystem所export出來的IRQ,然後才連到Nios II Processor。至於下圖中的Merlin IRQ Mapper則並不是必需的,若你在CPU subsystem中也有IP要使用interrupt,這必須再包一層Merlin IRQ Mapper;若你在CPU subsystem沒有IP要使用interrupt,只有Peripheral subsystem使用interrupt,可以直接只使用IRQ Bridge連接到Nios II Processor。

常見的錯誤(也是我第一次的錯誤)是直接將Peripheral subsystem所export的IRQ直接連到Nios II Processor,這樣Qsys與Quartus II編譯都沒有任何錯誤,Nios II也沒有錯誤,不過Nios II的C code將收不到來自Peripheral subsystem的interrupt。

irq000

2.如何避開Nios II SBT目前無法自動產生IRQ number常數在system.h的bug?

除此之外,在[2] Quartus II 11.0 Release Notes的p.15已經承認在Quartus II 11.0有以下的bug。

irq001

簡單的說,就是若你在subsystem中使用interrupt,當你使用Generate BSP時,Nios II SBT根據*.sopcinfo在system.h所產生相對應的IRQ number常數,永遠都是-1,並無法反應出目前硬體架構中真正的IRQ number。且經過實測,這個問題在Quartus II 11.1也依然存在。

如圖所示,我們對push button使用interrupt,但在system.h的PERIPHERAL_SYSTEM_BUTTON_PIO_IRQ常數卻是-1,與在Qsys上的IRQ number不同。

irq002

這會造成什麼影響呢?只要你的App project使用到有使用interrupt的IP,編譯就會產生錯誤,如下圖我們在system timer有使用interrupt,所以一編譯就產生錯誤無法繼續。

irq003

詳細錯誤訊息如下:

Error: Interrupt not connected for peripheral_system_timer_0. The system clock driver requires an interrupt to be connected. Please select an IRQ for this device in SOPC builder.

root cause就是system.h的IRQ number都是-1,所以App project找不到該IP的IRQ number而無法編譯。

Solution
既然在system.h的IRQ number都是-1,我們只好重新自己在system.h手動定義IRQ number。根據[3] Altera Wiki : New Qsys Issues for Interrupts的建議

irq014

當然你可以直接去修改system.h,但別忘了BSP project的所有檔案最好不要手動修改,應該交由Nios II SBT或者command line script去修改才對,因為每當你執行Generate BSP或者BSP Editor時,Nios II SBT都會重新產生system.h,也就是你做的所有修改都會被覆蓋掉。所以[3] Altera Wiki : New Qsys Issues for Interrupts 的解法雖然可行,但並不完美。

根據 [2] Quartus II 11.0 Release Notes的建議

irq001

看起來是要我們自己另開一個my_system.h,然後將system.h所有內容複製到system.h,自己在my_system.h加上IRQ number常數,並且App project也使用my_system.h,這樣Generate BSP與BSP Editor就不會改到我的my_system.h了。

這樣看似理想,但卻衍生另外一個問題:BSP project有大量的檔案都include "system.h",你必須手動一一的改成include "my_system.h",這也是個大工程。所以[2] Quartus II 11.0 Release Notes 看似也不盡理想。

我在此提供一個小技巧對付Nios II SBT目前這個bug。

在system.h的尾部自己加上IP IRQ number的定義如下圖,先執行#undef取消這個常數的定義,再用#define重新這個常數,因為若同一個常數在system.h重複#define,會產生warning,若使用#undef就完全沒有warning。

irq005

然後將這些#undef與#define另存一個文字檔,每當你執行Generate BSP或者BSP Editor時,system.h就會被Nios II SBT重新產生蓋掉你原先的設定,再將這些#undef與#define貼到system.h的最下方。如此就只需修改system.h,其他BSP檔案都不用做任何修改。

如此修改重新編譯後,就可順利Build Project,沒有任何錯誤。

irq006

3.如何在App project使用Interrupt?

根據[4] Exception Handling p.8-16與p.8-17的建議,我們將App project寫成如下的code使用interrupt。

nios2_onchip_leg_push_button.c / C

 1 /* 
2 (C) OOMusou 2011 http://oomusou.cnblogs.com
3
4 Filename : nios2_onchip_led_push_button.c
5 Compiler : Nios II SBT 11.0
6 Description : test led, push_button & interrupt in subsystem
7 Release : Jan.06,2012 1.0
8 */
9
10 #include <stdio.h>
11 #include "system.h"
12 #include "alt_types.h"
13 #include "sys/alt_irq.h"
14 #include "altera_avalon_pio_regs.h"
15
16 volatile int edge_capture;
17
18 #ifdef ALT_ENHANCED_INTERRUPT_API_PRESENT
19 void handle_key_interrupts(void *context) {
20 #else
21 void handle_key_interrupts(void *context, alt_u32 id) {
22 #endif
23
24 volatile int *edge_capture_ptr = (volatile int*)context;
25 *edge_capture_ptr = IORD_ALTERA_AVALON_PIO_EDGE_CAP(PERIPHERAL_SYSTEM_BUTTON_PIO_BASE);
26 IOWR_ALTERA_AVALON_PIO_EDGE_CAP(PERIPHERAL_SYSTEM_BUTTON_PIO_BASE, 0);
27
28 if (edge_capture == 0x01) {
29 printf("key 1 pressed!\n");
30 IOWR(PERIPHERAL_SYSTEM_LED_PIO_BASE, 0x00, 0xFE);
31 edge_capture = 0x00;
32 }
33 else if (edge_capture == 0x02) {
34 printf("key 2 pressed\n");
35 IOWR(PERIPHERAL_SYSTEM_LED_PIO_BASE, 0x00, 0xFD);
36 edge_capture = 0x00;
37 }
38 else if (edge_capture == 0x04) {
39 printf("key 3 pressed\n");
40 IOWR(PERIPHERAL_SYSTEM_LED_PIO_BASE, 0x00, 0xFB);
41 edge_capture = 0x00;
42 }
43 else if (edge_capture == 0x08) {
44 printf("key 4 pressed\n");
45 IOWR(PERIPHERAL_SYSTEM_LED_PIO_BASE, 0x00, 0xF7);
46 edge_capture = 0x00;
47 }
48 else if (edge_capture == 0x10) {
49 printf("key 5 pressed\n");
50 IOWR(PERIPHERAL_SYSTEM_LED_PIO_BASE, 0x00, 0xEF);
51 edge_capture = 0x00;
52 }
53 else if (edge_capture == 0x20) {
54 printf("key 6 pressed\n");
55 IOWR(PERIPHERAL_SYSTEM_LED_PIO_BASE, 0x00, 0xDF);
56 edge_capture = 0x00;
57 }
58 else if (edge_capture == 0x40) {
59 printf("key 7 pressed\n");
60 IOWR(PERIPHERAL_SYSTEM_LED_PIO_BASE, 0x00, 0xBF);
61 edge_capture = 0x00;
62 }
63 else if (edge_capture == 0x80) {
64 printf("key 8 pressed\n");
65 IOWR(PERIPHERAL_SYSTEM_LED_PIO_BASE, 0x00, 0x7F);
66 edge_capture = 0x00;
67 }
68 }
69
70
71 void init_key() {
72 void *edge_capture_ptr = (void *)&edge_capture;
73 IOWR_ALTERA_AVALON_PIO_IRQ_MASK(PERIPHERAL_SYSTEM_BUTTON_PIO_BASE, 0xFF);
74 IOWR_ALTERA_AVALON_PIO_EDGE_CAP(PERIPHERAL_SYSTEM_BUTTON_PIO_BASE, 0x0);
75
76 #ifdef ALT_ENHANCED_INTERRUPT_API_PRESENT
77 alt_ic_isr_register(PERIPHERAL_SYSTEM_BUTTON_PIO_IRQ_INTERRUPT_CONTROLLER_ID,
78 PERIPHERAL_SYSTEM_BUTTON_PIO_IRQ,
79 handle_key_interrupts,
80 edge_capture_ptr,
81 0x0);
82 #else
83
84 alt_irq_register(PERIPHERAL_SYSTEM_BUTTON_PIO_IRQ,
85 edge_capture_ptr,
86 handle_key_interrupts);
87 #endif
88 }
89
90
91 int main() {
92 printf("Nios II + Onchip + LED + Push Button Test!\n");
93
94 init_key();
95
96 while(1);
97
98 return 0;
99 }

以上的code我不打算一行一行講解,詳細請參考[4] Exception Handling p.8-16與p.8-17,我要強調的是,一般在使用interrupt時,Altera都會建議你使用新的alt_ic_isr_register(),而不要使用舊的alt_irq_register(),並且說未來Nios II SBT版本將只支援alt_ic_isr_register(),若在只有一層Qsys的system下,可以使用alt_ic_isr_register()沒有問題,但在具有Qsys subsystem下使用interrupt時,若使用alt_ic_isr_register()將會造成編譯錯誤,會說找不到alt_ic_isr_register(),為什麼會這樣呢?

在一般只有一層Qsys system,在system.h可以看到#define ALT_ENHANCED_INTERRUPT_API_PRESENT,如下圖所示:

irq007

但在使用Qsys subsystem的system.h下,看不到#define ALT_ENHANCED_INTERRUPT_API_PRESENT

irq008

在BSP的

sys/alt_irq.h / C

  1 #ifndef __ALT_IRQ_H__
2 #define __ALT_IRQ_H__
3
4 /******************************************************************************
5 * *
6 * License Agreement *
7 * *
8 * Copyright (c) 2009 Altera Corporation, San Jose, California, USA. *
9 * All rights reserved. *
10 * *
11 * Permission is hereby granted, free of charge, to any person obtaining a *
12 * copy of this software and associated documentation files (the "Software"), *
13 * to deal in the Software without restriction, including without limitation *
14 * the rights to use, copy, modify, merge, publish, distribute, sublicense, *
15 * and/or sell copies of the Software, and to permit persons to whom the *
16 * Software is furnished to do so, subject to the following conditions: *
17 * *
18 * The above copyright notice and this permission notice shall be included in *
19 * all copies or substantial portions of the Software. *
20 * *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *
26 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *
27 * DEALINGS IN THE SOFTWARE. *
28 * *
29 * This agreement shall be governed in all respects by the laws of the State *
30 * of California and by the laws of the United States of America. *
31 * *
32 ******************************************************************************/
33
34 /*
35 * alt_irq.h is the Nios II specific implementation of the interrupt controller
36 * interface.
37 *
38 * Nios II includes optional support for an external interrupt controller.
39 * When an external controller is present, the "Enhanced" interrupt API
40 * must be used to manage individual interrupts. The enhanced API also
41 * supports the processor's internal interrupt controller. Certain API
42 * members are accessible from either the "legacy" or "enhanced" interrpt
43 * API.
44 *
45 * Regardless of which API is in use, this file should be included by
46 * application code and device drivers that register ISRs or manage interrpts.
47 */
48 #include <errno.h>
49
50 #include "nios2.h"
51 #include "alt_types.h"
52 #include "system.h"
53
54 #ifdef __cplusplus
55 extern "C"
56 {
57 #endif /* __cplusplus */
58
59 /*
60 * Macros used by alt_irq_enabled
61 */
62 #define ALT_IRQ_ENABLED 1
63 #define ALT_IRQ_DISABLED 0
64
65 /*
66 * Number of available interrupts in internal interrupt controller.
67 */
68 #define ALT_NIRQ NIOS2_NIRQ
69
70 /*
71 * Used by alt_irq_disable_all() and alt_irq_enable_all().
72 */
73 typedef int alt_irq_context;
74
75 /* ISR Prototype */
76 #ifdef ALT_ENHANCED_INTERRUPT_API_PRESENT
77 typedef void (*alt_isr_func)(void* isr_context);
78 #else
79 typedef void (*alt_isr_func)(void* isr_context, alt_u32 id);
80 #endif
81
82 /*
83 * The following protypes and routines are supported by both
84 * the enhanced and legacy interrupt APIs
85 */
86
87 /*
88 * alt_irq_enabled can be called to determine if the processor's global
89 * interrupt enable is asserted. The return value is zero if interrupts
90 * are disabled, and non-zero otherwise.
91 *
92 * Whether the internal or external interrupt controller is present,
93 * individual interrupts may still be disabled. Use the other API to query
94 * a specific interrupt.
95 */
96 static ALT_INLINE int ALT_ALWAYS_INLINE alt_irq_enabled (void)
97 {
98 int status;
99
100 NIOS2_READ_STATUS (status);
101
102 return status & NIOS2_STATUS_PIE_MSK;
103 }
104
105 /*
106 * alt_irq_disable_all()
107 *
108 * This routine inhibits all interrupts by negating the status register PIE
109 * bit. It returns the previous contents of the CPU status register (IRQ
110 * context) which can be used to restore the status register PIE bit to its
111 * state before this routine was called.
112 */
113 static ALT_INLINE alt_irq_context ALT_ALWAYS_INLINE
114 alt_irq_disable_all (void)
115 {
116 alt_irq_context context;
117
118 NIOS2_READ_STATUS (context);
119
120 NIOS2_WRITE_STATUS (context & ~NIOS2_STATUS_PIE_MSK);
121
122 return context;
123 }
124
125 /*
126 * alt_irq_enable_all()
127 *
128 * Enable all interrupts that were previously disabled by alt_irq_disable_all()
129 *
130 * This routine accepts a context to restore the CPU status register PIE bit
131 * to the state prior to a call to alt_irq_disable_all().
132
133 * In the case of nested calls to alt_irq_disable_all()/alt_irq_enable_all(),
134 * this means that alt_irq_enable_all() does not necessarily re-enable
135 * interrupts.
136 *
137 * This routine will perform a read-modify-write sequence to restore only
138 * status.PIE if the processor is configured with options that add additional
139 * writeable status register bits. These include the MMU, MPU, the enhanced
140 * interrupt controller port, and shadow registers. Otherwise, as a performance
141 * enhancement, status is overwritten with the prior context.
142 */
143 static ALT_INLINE void ALT_ALWAYS_INLINE
144 alt_irq_enable_all (alt_irq_context context)
145 {
146 #if (NIOS2_NUM_OF_SHADOW_REG_SETS > 0) || (defined NIOS2_EIC_PRESENT) || \
147 (defined NIOS2_MMU_PRESENT) || (defined NIOS2_MPU_PRESENT)
148 alt_irq_context status;
149
150 NIOS2_READ_STATUS (status);
151
152 status &= ~NIOS2_STATUS_PIE_MSK;
153 status |= (context & NIOS2_STATUS_PIE_MSK);
154
155 NIOS2_WRITE_STATUS (status);
156 #else
157 NIOS2_WRITE_STATUS (context);
158 #endif
159 }
160
161 /*
162 * The function alt_irq_init() is defined within the auto-generated file
163 * alt_sys_init.c. This function calls the initilization macros for all
164 * interrupt controllers in the system at config time, before any other
165 * non-interrupt controller driver is initialized.
166 *
167 * The "base" parameter is ignored and only present for backwards-compatibility.
168 * It is recommended that NULL is passed in for the "base" parameter.
169 */
170 extern void alt_irq_init (const void* base);
171
172 /*
173 * alt_irq_cpu_enable_interrupts() enables the CPU to start taking interrupts.
174 */
175 static ALT_INLINE void ALT_ALWAYS_INLINE
176 alt_irq_cpu_enable_interrupts ()
177 {
178 NIOS2_WRITE_STATUS(NIOS2_STATUS_PIE_MSK
179 #if defined(NIOS2_EIC_PRESENT) && (NIOS2_NUM_OF_SHADOW_REG_SETS > 0)
180 | NIOS2_STATUS_RSIE_MSK
181 #endif
182 );
183 }
184
185
186 /*
187 * Prototypes for the enhanced interrupt API.
188 */
189 #ifdef ALT_ENHANCED_INTERRUPT_API_PRESENT
190 /*
191 * alt_ic_isr_register() can be used to register an interrupt handler. If the
192 * function is succesful, then the requested interrupt will be enabled upon
193 * return.
194 */
195 extern int alt_ic_isr_register(alt_u32 ic_id,
196 alt_u32 irq,
197 alt_isr_func isr,
198 void *isr_context,
199 void *flags);
200
201 /*
202 * alt_ic_irq_enable() and alt_ic_irq_disable() enable/disable a specific
203 * interrupt by using IRQ port and interrupt controller instance.
204 */
205 int alt_ic_irq_enable (alt_u32 ic_id, alt_u32 irq);
206 int alt_ic_irq_disable(alt_u32 ic_id, alt_u32 irq);
207
208 /*
209 * alt_ic_irq_enabled() indicates whether a specific interrupt, as
210 * specified by IRQ port and interrupt controller instance is enabled.
211 */
212 alt_u32 alt_ic_irq_enabled(alt_u32 ic_id, alt_u32 irq);
213
214 #else
215 /*
216 * Prototypes for the legacy interrupt API.
217 */
218 #include "priv/alt_legacy_irq.h"
219 #endif
220
221
222 /*
223 * alt_irq_pending() returns a bit list of the current pending interrupts.
224 * This is used by alt_irq_handler() to determine which registered interrupt
225 * handlers should be called.
226 *
227 * This routine is only available for the Nios II internal interrupt
228 * controller.
229 */
230 #ifndef NIOS2_EIC_PRESENT
231 static ALT_INLINE alt_u32 ALT_ALWAYS_INLINE alt_irq_pending (void)
232 {
233 alt_u32 active;
234
235 NIOS2_READ_IPENDING (active);
236
237 return active;
238 }
239 #endif
240
241 #ifdef __cplusplus
242 }
243 #endif /* __cplusplus */
244
245 #endif /* __ALT_IRQ_H__ */

186行

 1 /*
2 * Prototypes for the enhanced interrupt API.
3 */
4 #ifdef ALT_ENHANCED_INTERRUPT_API_PRESENT
5 /*
6 * alt_ic_isr_register() can be used to register an interrupt handler. If the
7 * function is succesful, then the requested interrupt will be enabled upon
8 * return.
9 */
10 extern int alt_ic_isr_register(alt_u32 ic_id,
11 alt_u32 irq,
12 alt_isr_func isr,
13 void *isr_context,
14 void *flags);
15
16 /*
17 * alt_ic_irq_enable() and alt_ic_irq_disable() enable/disable a specific
18 * interrupt by using IRQ port and interrupt controller instance.
19 */
20 int alt_ic_irq_enable (alt_u32 ic_id, alt_u32 irq);
21 int alt_ic_irq_disable(alt_u32 ic_id, alt_u32 irq);
22
23 /*
24 * alt_ic_irq_enabled() indicates whether a specific interrupt, as
25 * specified by IRQ port and interrupt controller instance is enabled.
26 */
27 alt_u32 alt_ic_irq_enabled(alt_u32 ic_id, alt_u32 irq);
28
29 #else
30 /*
31 * Prototypes for the legacy interrupt API.
32 */
33 #include "priv/alt_legacy_irq.h"
34 #endif

我們可以發現,當system.h有定義ALT_ENHANCED_INTERRUPT_API_PRESENT常數時,就有alt_ic_isr_register()可用,若沒定義,則#inlclude priv/alt_legacy_irq.h

alt_legacy_irq.h / C

  1 #ifndef __ALT_LEGACY_IRQ_H__
2 #define __ALT_LEGACY_IRQ_H__
3
4 /******************************************************************************
5 * *
6 * License Agreement *
7 * *
8 * Copyright (c) 2009 Altera Corporation, San Jose, California, USA. *
9 * All rights reserved. *
10 * *
11 * Permission is hereby granted, free of charge, to any person obtaining a *
12 * copy of this software and associated documentation files (the "Software"), *
13 * to deal in the Software without restriction, including without limitation *
14 * the rights to use, copy, modify, merge, publish, distribute, sublicense, *
15 * and/or sell copies of the Software, and to permit persons to whom the *
16 * Software is furnished to do so, subject to the following conditions: *
17 * *
18 * The above copyright notice and this permission notice shall be included in *
19 * all copies or substantial portions of the Software. *
20 * *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *
26 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *
27 * DEALINGS IN THE SOFTWARE. *
28 * *
29 * This agreement shall be governed in all respects by the laws of the State *
30 * of California and by the laws of the United States of America. *
31 * *
32 ******************************************************************************/
33
34 /*
35 * This file provides prototypes and inline implementations of certain routines
36 * used by the legacy interrupt API. Do not include this in your driver or
37 * application source files, use "sys/alt_irq.h" instead to access the proper
38 * public API.
39 */
40
41 #include <errno.h>
42 #include "system.h"
43
44 #ifndef NIOS2_EIC_PRESENT
45
46 #include "nios2.h"
47 #include "alt_types.h"
48
49 #include "sys/alt_irq.h"
50
51 #ifdef __cplusplus
52 extern "C"
53 {
54 #endif /* __cplusplus */
55
56 /*
57 * alt_irq_register() can be used to register an interrupt handler. If the
58 * function is succesful, then the requested interrupt will be enabled upon
59 * return.
60 */
61 extern int alt_irq_register (alt_u32 id,
62 void* context,
63 alt_isr_func handler);
64
65 /*
66 * alt_irq_disable() disables the individual interrupt indicated by "id".
67 */
68 static ALT_INLINE int ALT_ALWAYS_INLINE alt_irq_disable (alt_u32 id)
69 {
70 alt_irq_context status;
71 extern volatile alt_u32 alt_irq_active;
72
73 status = alt_irq_disable_all ();
74
75 alt_irq_active &= ~(1 << id);
76 NIOS2_WRITE_IENABLE (alt_irq_active);
77
78 alt_irq_enable_all(status);
79
80 return 0;
81 }
82
83 /*
84 * alt_irq_enable() enables the individual interrupt indicated by "id".
85 */
86 static ALT_INLINE int ALT_ALWAYS_INLINE alt_irq_enable (alt_u32 id)
87 {
88 alt_irq_context status;
89 extern volatile alt_u32 alt_irq_active;
90
91 status = alt_irq_disable_all ();
92
93 alt_irq_active |= (1 << id);
94 NIOS2_WRITE_IENABLE (alt_irq_active);
95
96 alt_irq_enable_all(status);
97
98 return 0;
99 }
100
101 #ifndef ALT_EXCEPTION_STACK
102 /*
103 * alt_irq_initerruptable() should only be called from within an ISR. It is used
104 * to allow higer priority interrupts to interrupt the current ISR. The input
105 * argument, "priority", is the priority, i.e. interrupt number of the current
106 * interrupt.
107 *
108 * If this function is called, then the ISR is required to make a call to
109 * alt_irq_non_interruptible() before returning. The input argument to
110 * alt_irq_non_interruptible() is the return value from alt_irq_interruptible().
111 *
112 * Care should be taken when using this pair of functions, since they increasing
113 * the system overhead associated with interrupt handling.
114 *
115 * If you are using an exception stack then nested interrupts won't work, so
116 * these functions are not available in that case.
117 */
118 static ALT_INLINE alt_u32 ALT_ALWAYS_INLINE alt_irq_interruptible (alt_u32 priority)
119 {
120 extern volatile alt_u32 alt_priority_mask;
121 extern volatile alt_u32 alt_irq_active;
122
123 alt_u32 old_priority;
124
125 old_priority = alt_priority_mask;
126 alt_priority_mask = (1 << priority) - 1;
127
128 NIOS2_WRITE_IENABLE (alt_irq_active & alt_priority_mask);
129
130 NIOS2_WRITE_STATUS (1);
131
132 return old_priority;
133 }
134
135 /*
136 * See Comments above for alt_irq_interruptible() for an explanation of the use of this
137 * function.
138 */
139 static ALT_INLINE void ALT_ALWAYS_INLINE alt_irq_non_interruptible (alt_u32 mask)
140 {
141 extern volatile alt_u32 alt_priority_mask;
142 extern volatile alt_u32 alt_irq_active;
143
144 NIOS2_WRITE_STATUS (0);
145
146 alt_priority_mask = mask;
147
148 NIOS2_WRITE_IENABLE (mask & alt_irq_active);
149 }
150 #endif /* ALT_EXCEPTION_STACK */
151
152 #ifdef __cplusplus
153 }
154 #endif /* __cplusplus */
155
156 #endif /* NIOS2_EIC_PRESENT */
157
158 #endif /* __ALT_LEGACY_IRQ_H__ */

61行

extern int alt_irq_register (alt_u32 id, 
void* context,
alt_isr_func handler);

則是我們所用舊的alt_irq_register()。

至於ISR的prototype新舊不一樣,trace的方式也一樣,就不再贅述。

至於為什麼目前在subsystem的interrupt只能使用舊的ISR register方式,我並不清楚,或許Quartus II未來版本會有所改變。

使用以上方法後,就可正確的在App project收到subsystem的interrupt了。

irq011

Conclusion
我們在本文看到了Qsys與SOPC Builder在subsystem與interrupt的處理有很大的差異,也看到了目前Qsys與Nios II SBT尚有些bug待修正。目前Quartus II 11.0與Quartus II 11.1都還有system.h的bug,相信未來的版本一定會修正這個問題。假如你現在要在subsystem使用interrupt,可暫時使用本文的方式當作short term solution。

Reference
[1] Qsys Interconnect
[2] Quartus II 11.0 Release Notes
[3] Altera Wiki : New Qsys Issues for Interrupts
[4] Exception Handling

全文完。