source: rtems/c/src/lib/libbsp/arm/tms570/irq/irq.c @ 38404cb

5
Last change on this file since 38404cb was 870ff8e9, checked in by Pavel Pisa <pisa@…>, on 11/12/15 at 22:11:31

bsp/tms570: use POM only when application image does not start at address 0.

Parameters overlay module is initialized and cleared first.
It is used later to replace exception target vectors
only if that is required.

The application loader code with CPU and SDRAM setup
code has to provide well defined pattern of instructions
at addresses 0x00000000 and 0x0000001f, because only data
read accesses can be processed reliably by POM. The expected
instruction pattern can be seen in the next example

https://github.com/hornmich/tms570ls3137-hdk-sdram/blob/master/SDRAM_SCI_configuration/source/sys_intvecs.asm

Comments with detailed description of code, background
and reasons for selected approach have been included
in TMS570 bsp startup code.

Signed-off-by: Pavel Pisa <pisa@…>
Signed-off-by: Premysl Houdek <kom541000@…>

  • Property mode set to 100644
File size: 6.2 KB
Line 
1/**
2 * @file irq.c
3 *
4 * @ingroup tms570
5 *
6 * @brief TMS570 interrupt support functions definitions.
7 */
8
9/*
10 * Copyright (c) 2014 Premysl Houdek <kom541000@gmail.com>
11 *
12 * Google Summer of Code 2014 at
13 * Czech Technical University in Prague
14 * Zikova 1903/4
15 * 166 36 Praha 6
16 * Czech Republic
17 *
18 * Based on LPC24xx and LPC1768 BSP
19 *
20 * The license and distribution terms for this file may be
21 * found in the file LICENSE in this distribution or at
22 * http://www.rtems.org/license/LICENSE.
23 */
24
25#include <bsp.h>
26#include <bsp/irq-generic.h>
27#include <bsp/tms570-vim.h>
28#include <bsp/irq.h>
29#include <rtems/score/armv4.h>
30
31/**
32 * @brief Check if isr vector is valid
33 *
34 * Check if isr vector is valid by using BSP_INTERRUPT_VECTOR_MAX and
35 * BSP_INTERRUPT_VECTOR_MIN defined in irq.h
36 *
37 * @param[in] vector interrupt vector to be checked.
38 * @retval TRUE vector is valid.
39 * @retval FALSE vector is invalid
40 */
41static inline bool tms570_irq_is_valid(
42  rtems_vector_number vector
43)
44{
45  return (vector <= BSP_INTERRUPT_VECTOR_MAX) &&
46         (vector > BSP_INTERRUPT_VECTOR_MIN);
47}
48
49unsigned int priorityTable[BSP_INTERRUPT_VECTOR_MAX+1];
50
51/**
52 * @brief Set priority of the interrupt vector.
53 *
54 * This function is here because of compability. It should set
55 * priority of the interrupt vector.
56 * @warning It does not set any priority at HW layer. It is nearly imposible to
57 * @warning set priority of the interrupt on TMS570 in a nice way.
58 * @param[in] vector vector of isr
59 * @param[in] priority new priority assigned to the vector
60 * @return Void
61 */
62void tms570_irq_set_priority(
63  rtems_vector_number vector,
64  unsigned priority
65)
66{
67  if ( tms570_irq_is_valid(vector) ) {
68    priorityTable[vector] = priority;
69  }
70}
71
72/**
73 * @brief Gets priority of the interrupt vector.
74 *
75 * This function is here because of compability. It returns priority
76 * of the isr vector last set by tms570_irq_set_priority function.
77 *
78 * @warning It does not return any real priority of the HW layer.
79 * @param[in] vector vector of isr
80 * @retval 0 vector is invalid.
81 * @retval priority priority of the interrupt
82 */
83unsigned tms570_irq_get_priority(
84  rtems_vector_number vector
85)
86{
87  if ( tms570_irq_is_valid(vector) ) {
88   return priorityTable[vector];
89 }
90 return 0;
91}
92
93/**
94 * @brief Interrupt dispatch
95 *
96 * Called by OS to determine which interrupt occured.
97 * Function passes control to interrupt handler.
98 *
99 * @return Void
100 */
101void bsp_interrupt_dispatch(void)
102{
103  rtems_vector_number vector = TMS570_VIM.IRQINDEX-1;
104
105  bsp_interrupt_handler_dispatch(vector);
106}
107
108/**
109 * @brief enables interrupt vector in the HW
110 *
111 * Enables HW interrupt for specified vector
112 *
113 * @param[in] vector vector of the isr which needs to be enabled.
114 * @retval RTEMS_INVALID_ID vector is invalid.
115 * @retval RTEMS_SUCCESSFUL interrupt source enabled.
116 */
117rtems_status_code bsp_interrupt_vector_enable(
118  rtems_vector_number vector
119)
120{
121  if( !tms570_irq_is_valid(vector) ) {
122    return RTEMS_INVALID_ID;
123  }
124
125  TMS570_VIM.REQENASET[vector >> 5] = 1 << (vector & 0x1f);
126
127  return RTEMS_SUCCESSFUL;
128}
129
130/**
131 * @brief disables interrupt vector in the HW
132 *
133 * Disables HW interrupt for specified vector
134 *
135 * @param[in] vector vector of the isr which needs to be disabled.
136 * @retval RTEMS_INVALID_ID vector is invalid.
137 * @retval RTEMS_SUCCESSFUL interrupt source disabled.
138 */
139rtems_status_code bsp_interrupt_vector_disable(
140  rtems_vector_number vector
141)
142{
143  if( !tms570_irq_is_valid(vector) ) {
144    return RTEMS_INVALID_ID;
145  }
146
147  TMS570_VIM.REQENACLR[vector >> 5] = 1 << (vector & 0x1f);
148
149  return RTEMS_SUCCESSFUL;
150}
151
152/**
153 * @brief Init function of interrupt module
154 *
155 * Resets vectored interrupt interface to default state.
156 * Disables all interrupts.
157 * Set all sources as IRQ (not FIR).
158 *
159 * @retval RTEMS_SUCCESSFUL All is set
160 */
161rtems_status_code bsp_interrupt_facility_initialize(void)
162{
163  void (**vim_vec)(void) = (void (**)(void)) 0xFFF82000;
164  unsigned int value = 0x00010203;
165  unsigned int i = 0;
166  uint32_t sctlr;
167
168  /* Disable interrupts */
169  for ( i = 0; i < 3; i++ ) {
170    TMS570_VIM.REQENACLR[i] = 0xffffffff;
171  }
172  /* Map default events on interrupt vectors */
173  for ( i = 0; i < 24; i += 1, value += 0x04040404) {
174    TMS570_VIM.CHANCTRL[i] = value;
175  }
176  /* Set all vectors as IRQ (not FIR) */
177  TMS570_VIM.FIRQPR[0] = 3;
178  TMS570_VIM.FIRQPR[1] = 0;
179  TMS570_VIM.FIRQPR[2] = 0;
180
181  /*
182    _CPU_ISR_install_vector(
183        ARM_EXCEPTION_IRQ,
184        _ARMV4_Exception_interrupt,
185        NULL
186    );
187
188    Call to setup of interrupt entry in CPU level exception vectors table
189    is not used (necessary/possible) because the table is provided
190    by c/src/lib/libbsp/arm/shared/start/start.S and POM overlay
191    solution remaps that to address zero.
192  */
193
194  for ( i = 0; i <= 94; ++i ) {
195    vim_vec[i] = _ARMV4_Exception_interrupt;
196  }
197  /* Clear bit VE in SCTLR register to not use VIM IRQ exception bypass*/
198  asm volatile ("mrc p15, 0, %0, c1, c0, 0\n": "=r" (sctlr));
199  /*
200   * Disable bypass of CPU level exception table for interrupt entry which
201   * can be provided by VIM hardware
202   */
203  sctlr &= ~(1 << 24);
204  #if 0
205    /*
206     * Option to enable exception table bypass for interrupts
207     *
208     * Because RTEMS requires all interrupts to be serviced through
209     * common _ARMV4_Exception_interrupt handler to allow task switching
210     * on exit from interrupt working correctly, vim_vec cannot point
211     * directly to individual vector handlers and need to point
212     * to single entry path. But if TMS570_VIM.IRQINDEX is then used
213     * to target execution to corresponding service then for some
214     * peripherals (i.e. EMAC) interrupt is already acknowledged
215     * by VIM and IRQINDEX is read as zero which leads to spurious
216     * interrupt and peripheral not serviced/blocked.
217     *
218     * To analyze this behavior we used trampolines which setup
219     * bsp_interrupt_vector_inject and pass execution to
220     * _ARMV4_Exception_interrupt. It works but is more ugly than
221     * use of POM remap for these cases where application does not
222     * start at address 0x00000000. If RTEMS image is placed at
223     * memory space beginning then no of these constructs is necessary.
224     */
225    sctlr |= 1 << 24;
226  #endif
227  asm volatile ("mcr p15, 0, %0, c1, c0, 0\n": : "r" (sctlr));
228
229  return RTEMS_SUCCESSFUL;
230}
Note: See TracBrowser for help on using the repository browser.