| | 1 | = GIET-VM / XCU Driver = |
| | 2 | |
| | 3 | [[PageOutline]] |
| | 4 | |
| | 5 | The [source:soft/giet_vm/giet_drivers/xcu_driver.c xcu_driver.c] and [source:soft/giet_vm/giet_drivers/xcu_driver.h xcu_driver.h] files define the XCU driver. |
| | 6 | |
| | 7 | The ''vci_xcu'' component is an extended interrupt controller, available in the SoCLib components library, and supporting three types of interrupts: |
| | 8 | * '''HWI''' : HardWare Interrupts (from hardware peripherals) |
| | 9 | * '''PTI''' : Programmable Timer Interrupts (contained in the XCU component) |
| | 10 | * '''WTI''' : Write Trigered Interrupts (from software, or from a PIC controller) |
| | 11 | |
| | 12 | The GIET-VM uses three 32 entries interrupt vectors (one interrupt vector for each interrupt type). |
| | 13 | |
| | 14 | The CXU component is a replicated peripheral: it must exist one XCU per cluster, and each one can contain several channels: |
| | 15 | The number of XICU channels is equal to NB_PROCS_MAX, because there is one private XCU channel per processor in a cluster. |
| | 16 | |
| | 17 | The virtual base address of the segment associated to the component is: |
| | 18 | vbase = SEG_XCU_BASE + cluster_xy * PERI_CLUSTER_INCREMENT |
| | 19 | |
| | 20 | The SEG_XCU_BASE and PERI_CLUSTER_INCREMENT values must be defined in the hard_config.h file. |
| | 21 | |
| | 22 | The addressable registers map is defined [source:soft/giet_vm/giet_drivers/xcu_driver.h here]. |
| | 23 | |
| | 24 | === void '''_xcu_set_mask'''( unsigned int cluster_xy, unsigned int channel, unsigned int mask, unsigned int irq_type ) === |
| | 25 | This function set the mask register for the IRQ type defined by "irq_type", |
| | 26 | and for the channel identified by the "cluster_xy" and "channel" arguments. |
| | 27 | All '1' bits are set / all '0' bits are not modified. |
| | 28 | |
| | 29 | === void '''_xcu_get_index'''( unsigned int cluster_xy, unsigned int channel, unsigned int * index, unsigned int * irq_type ) === |
| | 30 | This function returns the index and the type of the highest priority active interrupt: |
| | 31 | 1. active PTI (Timer Interrupt), |
| | 32 | 2. active HWI (Hardware Interrupt), |
| | 33 | 3. active WTI (Software Interrupt) |
| | 34 | |
| | 35 | === void '''_xcu_send_wti'''( unsigned int cluster_xy, unsigned int wti_index, unsigned int wdata ) === |
| | 36 | This function writes the ''wdata'' value in the mailbox defined by the ''cluster_xy'' and ''wti_inde'' arguments. |
| | 37 | |
| | 38 | === void '''_xcu_get_wti_value'''( unsigned int cluster_xy, unsigned int wti_index, unsigned int * value ) === |
| | 39 | This function returns the value contained in a WTI mailbox defined by the ''cluster_xy'' and ''wti_index'' arguments. This value is written in the ''value'' argument, and the corresponding WTI is acknowledged. |
| | 40 | |
| | 41 | === void '''_xcu_get_wti_address'''( unsigned int wti_index, unsigned int * address ) === |
| | 42 | This function returns the physical address of the WTI mailbox in cluster [0][0], defined by the ''wti_index'' argument, in the ''address'' argument. |
| | 43 | It is used by the GIET to configurate the IOPIC component. There is no access to a specific XCU component in a specific cluster. |
| | 44 | |
| | 45 | === void '''_xcu_timer_start'''( unsigned int cluster_xy, unsigned int pti_index, unsigned int period ) === |
| | 46 | This function activates a timer contained in XCU by writing in the proper register the period value. |
| | 47 | |
| | 48 | === void '''_xcu_timer_stop'''( unsigned int cluster_xy, unsigned int pti_index ) == |
| | 49 | This function desactivates a timer in XCU component by writing in the proper register. |
| | 50 | |
| | 51 | === unsigned int '''_xcu_timer_reset_irq'''( unsigned int cluster_xy, unsigned int pti_index ) === |
| | 52 | ////////////////////////////////////////////////////////////////////////////// |
| | 53 | // This function acknowlegge a timer interrupt in XCU |
| | 54 | // component by reading in the proper XCU register. |
| | 55 | // It can be used by both the isr_switch() for a "system" timer, |
| | 56 | // or by the _isr_timer() for an "user" timer. |
| | 57 | ////////////////////////////////////////////////////////////////////////////// |
| | 58 | |
| | 59 | extern void _xcu_timer_reset_cpt( unsigned int cluster_xy, |
| | 60 | unsigned int pti_index ); |
| | 61 | ////////////////////////////////////////////////////////////////////////////// |
| | 62 | // This function resets a timer counter. To do so, we re-write the period |
| | 63 | // in the proper register, what causes the count to restart. |
| | 64 | // The period value is read from the same (TIMER_PERIOD) register, |
| | 65 | // this is why in appearance we do nothing useful (read a value |
| | 66 | // from a register and write this value in the same register). |
| | 67 | // This function is called during a context switch (user or preemptive) |
| | 68 | ///////////////////////////////////////////////////////////////////////////// |
| | 69 | |