Dispatch
Dispatch
1 #ifndef DISPATCH_H
2 #define DISPATCH_H
3
4 #define RISCV_MACHINE_CALL_M
_MODE (11)
5
6 void syscall_dispatch(uint32_t code, uint32_t param);
7 void excepcion_dispatch(uint32_t code);
8 void irq_dispatch(uint32_t code);
9
10 void install_irq_handler( uint32_t irq_num, void (*f)(void) );
11 /*Esta función se utiliza para instalar/registrar un ISR (manejador de instrucciones) para un
número específico de instruccion IRQ
12 * irq_num: numero q identifica la IRQ q se quiere manejar(cada dispositivo/evento q puede
generar una interrupcion tiene un número asociado)
13 * void (*f): Puntero a una función q no recibe parámetros ni devuelve valores. Esto
significa q puedes pasar cualquier funcion q siga esta firma como argumento a install handler
14 * CUando se active la interrupcion correspondiete, el sistema llamará a f*/
15
16 void uninstall_irq_handle
r( uint32_t irq_num );
17 /*función q se utiliza para eliminar un ISR (manejador de instrucciones) previamente
instalado para un número específico de IQR. Si no quieres usar mas esa interrupcion, puedes
18 * puedes usar esta funcion para desregistrar el ISR asociado a la IRQ*/
19
20 void install_local_timer_
handler( void (*f)(void) );
21 void uninstall_local_time
r_handler();
22 void local_timer_set_gap( uint64_t gap );
23
24 void raise_SW_interrupt( uint32_t hart );
25
26 // SET STATUS REG MIE BIT (Global IRQ enable)
27 void enable_irq(void);
28 /*AL habilitar la función, el procesador será capaz de responder a cualquier
interrupción(interna o externa) q esté permitida en el sitema*/
29
30 // CLEAR STATUS REG MIE BIT (Global IRQ disable)
31 void disable_irq(void);
32 /*SI activamos esto el procesador NO ATENDERÁ NINGUNA INSTRUCCIÓN*/
33 // SET MIE REG EXT_IRQ BIT (EXT IRQ enable)
34 void enable_ext_irq(void);
35 /*Permite q el procesador responda a las interrupciones q provienen de dispositivos
externos(teclado). Internamente, la funcion ajusta el bit correspondiente en el registro
36 * MIE q controla las interrupciones externas. Al poner este bit a 1 el procesador queda
habilitado para atender cualquier instruccion externa. Al ejecutar esta instruccion
37 * cualquier interrupcion externa no enmascarada será atendida por el procesador cunado
ocurra*/
38
39 // CLEAR MIE REG EXT_IRQ BIT (EXT IRQ disable)
40 void disable_ext_irq(void);
41 /*Pone el bit q controla las interrupciones externas a 0, de esta forma, el procesador
ignorará todas las interrupciones externas hasta q se vuelva a habilitar*/
42 // SET MIE REG TIMER BIT (Timer irq enable)
43 void enable_timer_clinc_i
rq(void);
localhost:57236/1bbfe3f3-7687-43cf-84e3-372d9cb8a01d/ 1/2
10/1/25, 11:32 dispatch.h
44
45 // CLEAR MIE REG TIMER BIT (Timer irq disable)
46 void disable_timer_clinc_
irq(void);
47
48 // SET MIE REG SW BIT
49 void enable_SW_IRQ(void);
50
51 // CLEAR MIE REG SW BIT
52 void disable_SW_IRQ(void);
53
54 // MASK PLIC external IRQ
55 void plic_irq_mask(uint32_t source);
56 /* Se utiliza para enmascarar/ignorar interrupciones. Source es el número de la IQR q
queremos ignorar*/
57
58 // UNMASK PLIC external IRQ
59 void plic_irq_unmask(uint32_t source);
60 /*Desenmascara una instruccion previamente enmascarada y el procesador podrá manejarla*/
61
62 // syscall (Executive call)
63 void syscall(uint32_t N, uint32_t param );
64
65 #endif /* DISPATCH_H */
66
localhost:57236/1bbfe3f3-7687-43cf-84e3-372d9cb8a01d/ 2/2
10/1/25, 11:30 main.c
localhost:57236/90478b45-5b77-4995-ae05-c9331345804e/ 1/4
10/1/25, 11:30 main.c
52 #define CYCLIC_EXECUTIVE_PER
IOD_IN_SECONDS 10 //Segun la imagen de la ultima parte de la
practica
53
54 #define CYCLIC_EXECUTIVE_PER
IOD_IN_TICKS (CYCLIC_EXECUTIVE_PER
IOD_IN_SECONDS * CLINT_CLOCK)
55
56 #define CYCLIC_EXECUTIVE_HYP
ER_PERIOD 3
57 #define CYCLIC_EXECUTIVE_TAS
KS_NUMBER 4
58
59 void (*cyclic_executive[CYCLIC_EXECUTIVE_HYP
ER_PERIOD]
60 [CYCLIC_EXECUTIVE_TASKS_NUMBER+1])(void) = {
61 {TAvoidObstacle, TPathTracking, TSensorFusion, NULL, NULL}, //Periodo 0
62 {TAvoidObstacle, TCalculatePath, NULL, NULL, NULL}, //Periodo 1
63 {TAvoidObstacle, TPathTracking, NULL, NULL, NULL}, //Periodo 2
64 };
65
66 int main() {
67 // Inicialización de variables
68 uint8_t current_period = 0;
69 int task_index = 0;
70 uint64_t next_period_in_ticks
_from_reset;
71 // Inicialización de la hora de inicio
72 InitMonotonicClock(date_time_to_Y2K(12, 10, 23, 12, 40, 0)); // 12/10/2023 12:40
73 // Obtener la referencia de tiempo absoluta desde el reinicio
74 next_period_in_ticks
_from_reset = get_ticks_from_reset
();
75
76 while (1) {
77 task_index = 0; // Se reinicia al comienzo de cada periodo básico
78
79 printf("\nStart period: %d\n", current_period);
80 print_date_time_from
_Y2K(GetUniversalTime_Y2K
());
81
82 // Ejecutar las tareas de este periodo
83 while (cyclic_executive[current_period][task_index] != NULL) {
84 cyclic_executive[current_period][task_index](); // Ejecutar tarea
85 task_index++;
86 }
87
88 // Sincronización con el inicio del siguiente periodo
89 next_period_in_ticks
_from_reset += CYCLIC_EXECUTIVE_PER
IOD_IN_TICKS;
90 wait_until(next_period_in_ticks
_from_reset);
91
92 // Avanzar al siguiente periodo
93 current_period++;
94 if (current_period == CYCLIC_EXECUTIVE_HYP
ER_PERIOD) {
95 current_period = 0;
96 printf("\n****************\n");
97 printf("Next hyperperiod\n");
98 printf("\n****************\n");
99 }
100
101 }
102
103 return 0;
104 }
localhost:57236/90478b45-5b77-4995-ae05-c9331345804e/ 2/4
10/1/25, 11:30 main.c
105
106
107
108
109
110
111 /////////////////////////////////////////OTRO
EJEMPLO/////////////////////////////////////////
112
113 void emu_execution_time( uint32_t mseconds )
114 {
115
116 // Convertir milisegundos a ticks
117 uint64_t = (uint64_t)mseconds * (CLINT_CLOCK / 1000); //Convertir mseg a ticks
118 uint64_t start_ticks = get_ticks_from_reset
(); //Obtener ticks actuales
119 wait_until(start_ticks + ticks); //Esperar el tiempo calculado
120 }
121
122 // Task code T1
123 void Task1(void)
124 {
125 printf(" Start T1\n");
126 print_date_time_from
_Y2K(GetUniversalTime_Y2K
());
127 emu_execution_time(1000); //execution time 1000 ms
128 printf(" End T1\n");
129 print_date_time_from
_Y2K(GetUniversalTime_Y2K
());
130 }
131
132 // Task code T2
133 void Task2(void)
134 {
135 printf(" Start T2\n");
136 print_date_time_from
_Y2K(GetUniversalTime_Y2K
());
137 emu_execution_time(300); //execution time 300 ms
138 printf(" End T2\n");
139 print_date_time_from
_Y2K(GetUniversalTime_Y2K
());
140 }
141
142 // Task code T3
143 void Task3(void)
144 {
145 printf(" Start T3\n");
146 print_date_time_from
_Y2K(GetUniversalTime_Y2K
());
147 emu_execution_time(500); //execution time 500 ms
148 printf(" End T3\n");
149 print_date_time_from
_Y2K(GetUniversalTime_Y2K
());
150 }
151
152 // Definition of the configuration macros
153 // CLINT_CLOCK is 10000000
154 #define CYClIC_EXECUTIVE_PER
IOD_IN_SECONDS 2
155 #define CYClIC_EXECUTIVE_PER
IOD_IN_TICKS (CYClIC_EXECUTIVE_PER
IOD_IN_SECONDS\
156 * CLINT_CLOCK)
157
localhost:57236/90478b45-5b77-4995-ae05-c9331345804e/ 3/4
10/1/25, 11:30 main.c
localhost:57236/90478b45-5b77-4995-ae05-c9331345804e/ 4/4
10/1/25, 11:35 mainn.c
1 #include "log.h"
2 #include "riscv_types.h"
3 #include "factorial.h"
4 #include "riscv_uart.h"
5 #include "serialize.h"
6 #include "ccds_pus_format.h"
7 #include "ccds_pus_stdio.h"
8 #include "dispatch.h"
9 #include "riscv_monotonic_cloc
k.h"
10 #include "clinc.h"
11 #define TICKS_1SG 10000000
12 /*ESte programa tiene como objetivo demostrar el manejo de syscalls(interfaz para q el
usuario pueda solicitar servicios como acceso a archivos, manejo de procesos...) y
13 * excepciones (interrupciones q desvianel flujo normal de un programa, provocados por
errores o por ciertas instrucciones q el hardware debe manejar de manera especial)
14 * en un entorno de ejecucion de bajo nivel. El código esta diseñado para provocar llamadas
al sistema (syscalls) como excepciones que desencadenan situaciones de error,
15 * permitiendo observar cómo el sistema reacciona a ellas*/
16
17
18 //int main()
19 //{
20 // //ZONA SYSCALLS:
21 // printf("----------SyscallS--------------\n");
22 //
23 // printf("syscall 22\n");
24 // syscall(22, 1); //Llamada al sistema
25 //
26 // printf("syscall 15\n");
27 // syscall(15, 2);
28 //
29 // printf("----------EXCEPTIONS---------\n");
30 //
31 // printf("Write NULL pointer\n");
32 // uint32_t *p = 0; //Puntero que apunta a la direccion 0 (direccion donde tendria q
haber un entero de 32 bits)
33 // *p = 234; //Intenta escribir en la direccion 0, 234 dando lugar a una excepción
ya que la mayoria de los sistemas no permiten acceder a la dir. 0
34 //
35 // printf("READ NULL pointer\n");
36 // uint32_t x = *p; //Intentamos leer algo (almacenandolo en x) que está en una dirección
de memoria q no es válida
37 //
38 // printf("UNALIGNED WRITE\n");
39 // p = (uint32_t *)123; //Ahora asigna al puntero p una direccion no alineada (dato
alineado: aquel que se almacena en una direccion que es múltiplo de su tamaño de bytes)
40 // *p = 334; // Attempt to write an uint32_t value to an odd address
41 //
42 // printf("UNALIGNED READ\n");
43 // x = *p; // Attempt to read an uint32_t value from an odd address
44 //
localhost:57236/2f315283-fbaa-4833-ab82-f31cd919df30/ 1/5
10/1/25, 11:35 mainn.c
45 //// Excepción 4: Unaligned Load (Lectura no alineada) — Se genera cuando se intenta leer
un valor desde una dirección no alineada.
46 //// Excepción 5: Load Access Fault (Fallo de acceso de lectura) — Se genera al intentar
leer desde una dirección de memoria inválida o protegida.
47 //// Excepción 6: Unaligned Store (Escritura no alineada) — Se genera cuando se intenta
escribir un valor en una dirección no alineada.
48 //// Excepción 7: Store Access Fault (Fallo de acceso de escritura) — Se genera al
intentar escribir en una dirección de memoria inválida o protegida
49 //
50 // return 0;
51 //
52 //}
53
54
55 //#define ESC 27
56 //
57 //char car;
58 //volatile uint32_t flag = 0;
59 //uint32_t end = 0;
60 //
61 //
62 //// UART ISR handler
63 //// It is going to be called each time a new car is received
64 //void uart_rx_irq_handler (void) //Declaramos la funcion q vamos a llamar. Cada vez que
introduzcamos un caracter, esta funcion será llamada
65 //{
66 // car = (char)riscv_getchar();//GUardo en car el caracter q voy a recibir
67 // flag = 1;
68 //}
69 //
70 //int main()
71 //{
72 //
73 // // TX/RX enable
74 // riscv_uart_enable_TX
();
75 // riscv_uart_enable_RX
();
76 //
77 // // Install uart handler
78 // install_irq_handler( UART_IRQ, uart_rx_irq_handler );
79 //
80 // riscv_uart_enable_RI
(); // Enable RX irq
81 // plic_irq_unmask( UART_IRQ ); // Digo al procesador q puede manejar esa instruccion
82 // enable_ext_irq(); // Habilito interrupciones externas
83 // enable_irq(); // Global interrupt enable
84 //
85 // riscv_print_string("Programación de Dispositivos e Interfaces\n"); //Imprimo una cadena
de caracteres
86 //
87 // while( !end ) //COntinua funcionando hasta q end se pone en 1
88 // {
89 // if ( flag )
90 // {
91 // printf("%d: ", car);
92 // if ( car == ESC ) // ESC
localhost:57236/2f315283-fbaa-4833-ab82-f31cd919df30/ 2/5
10/1/25, 11:35 mainn.c
93 // {
94 // end = 1;
95 // }
96 // else
97 // {
98 // printf("%c\n", car);
99 // riscv_putchar(car);
100 // flag = 0;
101 // }
102 // }
103 // // else do nothing
104 // }
105 //
106 // printf("Program end\n");
107 // return 0;
108 //}
109
110 int32_t rec;
111 uint8_t tc_header[16];
112 uint32_t idx=0;
113 uint8_t dato;
114 uint8_t flag=0;
115 char * pchar="El telecomando se ha procesado correctamente\n"; //Defino un puntero con el
que luego imprimiré la cadena de caracteres
116
117 void uart_rx_irq_handler(void){
118
119 rec = riscv_getchar();
120 dato=(uint8_t)rec;
121 if(idx==0){
122 if(dato==0x1B){
123 tc_header[idx]=dato;
124 idx++;
125 }
126 }else{
127 if(idx<6){
128 tc_header[idx]=dato;
129 idx++;}
130 if(idx==6){
131 flag=1;
132 }
133 }
134
135 }
136
137 uint32_t ticks = 0;
138 uint32_t contador1 = 0;
139 uint32_t contador5 = 0;
140 uint8_t flag_1seg = 0;
141 uint8_t flag_5seg = 0;
142
143 void timer_handler(void)
144 {
145 contador1 ++;
localhost:57236/2f315283-fbaa-4833-ab82-f31cd919df30/ 3/5
10/1/25, 11:35 mainn.c
localhost:57236/2f315283-fbaa-4833-ab82-f31cd919df30/ 5/5
10/1/25, 11:36 mainnnn.c
1 #include "riscv_types.h"
2 #include "log.h"
3
4 #include "riscv_uart.h"
5
6 #include "tc_fifo.h"
7 #include "tm_tc_handling.h"
8 #include "serialize.h"
9 #include "dispatch.h"
10 #include "crc.h"
11
12 #include "epd_pus_mission.h"
13
14 void processTC(uint8_t tc_bytes[], uint32_t tc_len )
15 {
16 uint8_t tm_bytes[TC_FIFO_TAM_TC];
17 uint32_t tm_len;
18
19 uint16_t tm_seq_counter = 1;
20
21 uint16_t tc_packet_id = deserialize_uint16( &tc_bytes[0] );
22 uint16_t tc_packet_seq_ctrl = deserialize_uint16( &tc_bytes[2] );
23
24 uint16_t crc_received = deserialize_uint16( &tc_bytes[tc_len-2] );
25 uint16_t crc_calculated = cal_crc_16(tc_bytes, tc_len - 2);
26
27 printf("PacketID: %04X\n", tc_packet_id );
28 printf("PacketSeqCtrl %04X\n", tc_packet_seq_ctrl );
29 printf("[CRCs] Rec: 0x%04X Calc: 0x%04X\n", crc_received, crc_calculated );
30
31 if ( crc_received != crc_calculated )
32 {
33 printf("ERROR: CRC Error: TM(1,2)\n");
34
35 // CRC ERROR: Generate TM (1,2) - Reject
36 tm_len = build_response_tm_1_2(tm_bytes, tm_seq_counter++, tc_packet_id,
tc_packet_seq_ctrl, CRC_ERROR_CODE );
37 sendTM( tm_bytes, tm_len );
38 }
39 else
40 {
41 // TC response
42 uint8_t service_type = tc_bytes[7];
43 uint8_t service_subtype = tc_bytes[8];
44
45 if ( (service_type == 17) && (service_subtype == 1 ) )
46 {
47 // TO COMPLETE: Test ACK field
48
49 // Bit 3: ack of successful acceptance. 1=TM(1,1) required; 0=TM(1,1) not
required
50 // Bit 2: 0, not used.
localhost:57236/74f0ef6f-0c0d-4c3f-b5e2-bd51901d5820/ 1/3
10/1/25, 11:36 mainnnn.c
localhost:57236/74f0ef6f-0c0d-4c3f-b5e2-bd51901d5820/ 2/3
10/1/25, 11:36 mainnnn.c
101 riscv_uart_enable_TX
();
102 riscv_uart_enable_RX
();
103
104 // E/S por interrupción con mapeo socket
105 install_irq_handler( UART_IRQ, uart_rx_irq_handler ); // Install uart handler
106 riscv_uart_enable_RI
(); // Enable RX irq
107 plic_irq_unmask( UART_IRQ ); // PLIC UART irq unmask
108 enable_ext_irq(); // Enable [Link]
109 enable_irq(); // Global interrupt enable
110 install_local_timer_
handler( timer_handler );
111 local_timer_set_gap( 1000000 ); // CLINT timer clock is 10Mhz
112 enable_timer_clinc_i
rq();
113
114 while(1)
115 {
116 /*
117 * if FIFO is not empty
118 * POP TC in mutual exclusion to avoid UART IRQ
119 * Just print received TC
120 */
121
122 //----------
123 if ( tc_fifo_not_empty( &tc_fifo) )
124 {
125 plic_irq_mask( UART_IRQ ); // PLIC UART irq mask
126 tc_fifo_pop( &tc_fifo, tc_bytes, &tc_len );
127 plic_irq_unmask( UART_IRQ ); // PLIC UART irq unmask
128
129 print_buffer( tc_bytes, tc_len );
130 processTC( tc_bytes, tc_len );
131 }
132 //----------
133 }
134 return 0;
135 }
136
localhost:57236/74f0ef6f-0c0d-4c3f-b5e2-bd51901d5820/ 3/3
10/1/25, 11:31 riscv_monotonic_clock.c
1 /*
2 * riscv_monotonic_cloc
k.c
3 *
4 * Created on: Mar 15, 2020
5 * Author: user
6 */
7
8 #include "riscv_types.h"
9 #include "clinc.h"
10 #include "log.h"
11 #include "riscv_monotonic_cloc
k.h"
12
13 //*******************************************************************
14 /** \brief Universal Time Reference in seconds from 1/1/2000 */
15 static uint32_t UniversalTimeRefY2K;
16
17 //*******************************************************************
18
19 void InitMonotonicClock( uint32_t current_time )
20 {
21 UniversalTimeRefY2K = current_time;
22 }
23
24
25 uint32_t GetUniversalTime_Y2K
()
26 {
27 uint32_t seconds_from_boot;
28 seconds_from_boot = (uint32_t)(get_ticks_from_reset
()/CLINT_CLOCK); // WARNING, posible
lose of precision
29 return (UniversalTimeRefY2K+seconds_from_boot);
30 }
31
32 #define DAYS_TO_1_FEBRUARY 31
33 #define DAYS_TO_1_MARCH_NO_L
EAP_YEAR (DAYS_TO_1_FEBRUARY + 28)
34 #define DAYS_TO_1_APRIL_NO_L
EAP_YEAR (DAYS_TO_1_MARCH_NO_L
EAP_YEAR +31)
35 #define DAYS_TO_1_MAY_NO_LEA
P_YEAR (DAYS_TO_1_APRIL_NO_L
EAP_YEAR +30)
36 #define DAYS_TO_1_JUNE_NO_LE
AP_YEAR (DAYS_TO_1_MAY_NO_LEA
P_YEAR +31)
37 #define DAYS_TO_1_JULY_NO_LE
AP_YEAR (DAYS_TO_1_JUNE_NO_LE
AP_YEAR +30)
38 #define DAYS_TO_1_AUGUST_NO_
LEAP_YEAR (DAYS_TO_1_JULY_NO_LE
AP_YEAR +31)
39 #define DAYS_TO_1_SEPTEMBER_
NO_LEAP_YEAR (DAYS_TO_1_AUGUST_NO_
LEAP_YEAR +31)
40 #define DAYS_TO_1_OCTOBER_NO
_LEAP_YEAR (DAYS_TO_1_SEPTEMBER_
NO_LEAP_YEAR +30)
41 #define DAYS_TO_1_NOVEMBER_N
O_LEAP_YEAR (DAYS_TO_1_OCTOBER_NO
_LEAP_YEAR +31)
42 #define DAYS_TO_1_DECEMBER_N
O_LEAP_YEAR (DAYS_TO_1_NOVEMBER_N
O_LEAP_YEAR +30)
43
44 //*******************************************************************
45
46 void print_date_time_from
_Y2K(uint32_t seconds_from_y2K){
47
48 uint32_t aux;
49
50 uint8_t second;
51 uint8_t minute;
localhost:57236/5f3ea704-b1df-4b7a-8259-e8cc5edd9c78/ 1/4
10/1/25, 11:31 riscv_monotonic_clock.c
52 uint8_t hour;
53 uint16_t day;
54 uint8_t month;
55
56 uint32_t year;
57 uint8_t leap_year=0; //false
58
59 aux=seconds_from_y2K;
60
61 second=aux%60;
62
63 aux=(aux-second)/60; //minutes
64 minute=aux%60;
65
66 aux=(aux-minute)/60; //hours
67 hour=aux%24;
68
69 aux=(aux-hour)/24; //days
70
71 //Year
72
73 year=aux/365;
74
75 if (year>0){
76 day=aux-year*365;
77
78 if (day >= ((year-1)/4 +1))
79 day=day-((year-1)/4 +1);
80 else{
81 year--;
82 day=day+365-((year-1)/4 +1);
83 }
84
85 if(((year-1)%4)==0)
86 leap_year=1; // true
87
88 }else {
89 day=aux;
90 leap_year=1; //true
91 }
92
93 day++; //first day is 0
94
95 if(day >= (DAYS_TO_1_DECEMBER_N
O_LEAP_YEAR + 1*leap_year)){
96 month=12; day=day-(DAYS_TO_1_DECEMBER_N
O_LEAP_YEAR + 1*leap_year);
97 }else if(day >= (DAYS_TO_1_NOVEMBER_N
O_LEAP_YEAR + 1*leap_year)){
98 month=11; day=day-(DAYS_TO_1_NOVEMBER_N
O_LEAP_YEAR + 1*leap_year);
99 }else if(day >= (DAYS_TO_1_OCTOBER_NO
_LEAP_YEAR + 1*leap_year)){
100 month=10; day=day-(DAYS_TO_1_OCTOBER_NO
_LEAP_YEAR + 1*leap_year);
101 }else if(day >= (DAYS_TO_1_SEPTEMBER_
NO_LEAP_YEAR + 1*leap_year)){
102 month=9; day=day-(DAYS_TO_1_SEPTEMBER_
NO_LEAP_YEAR + 1*leap_year);
103 }else if(day >= (DAYS_TO_1_AUGUST_NO_
LEAP_YEAR + 1*leap_year)){
104 month=8; day=day-(aux-(DAYS_TO_1_AUGUST_NO_
LEAP_YEAR + 1*leap_year));
105 }else if(day >= (DAYS_TO_1_JULY_NO_LE
AP_YEAR + 1*leap_year)){
localhost:57236/5f3ea704-b1df-4b7a-8259-e8cc5edd9c78/ 2/4
10/1/25, 11:31 riscv_monotonic_clock.c
localhost:57236/5f3ea704-b1df-4b7a-8259-e8cc5edd9c78/ 3/4
10/1/25, 11:31 riscv_monotonic_clock.c
159 case(11):
160 total_days+=DAYS_TO_1_NOVEMBER_N
O_LEAP_YEAR+1*leap_year;break;
161 case(12):
162 total_days+=DAYS_TO_1_DECEMBER_N
O_LEAP_YEAR+1*leap_year;break;
163 }void delay( uint64_t ticks );
164 void wait_until( uint64_t ticks_from_reset );
165
166
167 total_days+= (day-1);
168
169 y2K=((total_days*24 + hour)*60 + minutes)*60 + seconds;
170
171 return y2K;
172 }
173
174 /*
175 uint64_t get_ticks_from_reset
()
176 {
177 return *p_clinc_mtime;
178 }
179 */
180
181 void delay( uint64_t ticks_to_wait )
182 {
183 uint64_t target_ticks = get_ticks_from_reset
() + ticks_to_wait;
184 uint64_t current_ticks;
185
186 do {
187 current_ticks = get_ticks_from_reset
();
188 } while ( current_ticks < target_ticks );
189 }
190
191 void wait_until( uint64_t target_ticks )
192 {
193 uint64_t current_ticks;
194
195 do {
196 current_ticks = get_ticks_from_reset
();
197 } while ( current_ticks < target_ticks );
198 }
199
localhost:57236/5f3ea704-b1df-4b7a-8259-e8cc5edd9c78/ 4/4
10/1/25, 11:33 riscv_monotonic_clock.h
1 #ifndef RISCV_MONOTONIC_H_
2 #define RISCV_MONOTONIC_H_
3
4 #define CLINT_CLOCK (10000000)
5
6 void InitMonotonicClock( uint32_t current_time );
7
8 uint32_t GetUniversalTime_Y2K
();
9
10 void print_date_time_from
_Y2K(uint32_t seconds_from_y2K);
11
12 uint32_t date_time_to_Y2K( uint8_t day, uint8_t month, uint8_t year,
13 uint8_t hour, uint8_t minutes, uint8_t seconds );
14
15 // uint64_t get_ticks_from_reset
();
16 #define get_ticks_from_reset
() ((volatile uint64_t)(*p_clinc_mtime))
17 void delay( uint64_t ticks_to_wait );
18 void wait_until( uint64_t ticks_from_reset );
19
20 //Cuando utilizo estas dos funciones, el define get_ticks_from_resetme dice que el puntero
clinc_mtime no está declarado
21
22 void delay( uint64_t ticks_to_wait );
23
24 void wait_until( uint64_t target_ticks );
25
26
27 //ASÍ SE HACEN LAS FUNCIONES ESTAS
28 void delay( uint64_t ticks_to_wait )
29 {
30 uint64_t target_ticks = get_ticks_from_reset
() + ticks_to_wait;
31 uint64_t current_ticks;
32
33 do {
34 current_ticks = get_ticks_from_reset
();
35 } while ( current_ticks < target_ticks );
36 }
37
38 void wait_until( uint64_t target_ticks )
39 {
40 uint64_t current_ticks;
41
42 do {
43 current_ticks = get_ticks_from_reset
();
44 } while ( current_ticks < target_ticks );
45 }
46
47 #endif /* RISCV_MONOTONIC_H_*/
48
localhost:57236/2d3d068a-ce88-48ee-a861-e21df6563949/ 1/1
10/1/25, 11:36 tm_tc_handling.c
1 #include "ccsds_pus_format.h"
2 #include "riscv_uart.h"
3
4 #include "serialize.h"
5 #include "crc.h"
6 #include "epd_pus_mission.h"
7 #include "tc_fifo.h"
8 #include "tm_tc_handling.h"
9
10 #include "log.h"
11
12 uint32_t idx=0;
13 uint32_t bytes_to_read=0; // Total bytes to read
14 uint8_t tc_buffer[TC_FIFO_TAM_TC];
15 uint32_t receiver_state = IDLE;
16
17 uint32_t counter = 0;
18
19 void timer_handler(void)
20 {
21 if ( counter != 0 )
22 {
23 counter--;
24
25 if ( counter == 0 )
26 {
27 receiver_state = IDLE;
28 idx=0;
29 }
30 }
31 }
32
33
34
35
36 void uart_rx_irq_handler(void){
37 uint8_t data;
38
39 data = riscv_getchar();
40
41 switch (receiver_state)
42 {
43 case IDLE:
44
45 // TO COMPLETE: Wait for TC HEADER start (0x1B)
46
47
48 if(data==0x1B)
49 {
50 tc_buffer[idx]=data;
51 idx++;
localhost:57236/44e087aa-8d84-458a-b82c-265fdfd2cb1d/ 1/6
10/1/25, 11:36 tm_tc_handling.c
52 receiver_state = READING_CCSDS_HEADER
;
53
54 counter = 10; // esperamos 10 ticks de una decima
55 }
56
57 break;
58 case READING_CCSDS_HEADER
:
59
60 // TO COMPLETE: Read TC HEADER
61 tc_buffer[idx] = data;
62 idx++;
63
64 if(idx == TC_HEADER_SIZE)//TC_HEADER_SIZE = 6
65 {
66 uint16_t packet_length = deserialize_uint16(&tc_buffer[4]);
67 bytes_to_read = 6 + packet_length + 1;
68 receiver_state = READING_PACKET_DF;
69
70 }
71
72
73 break;
74 case READING_PACKET_DF:
75
76
77 // TO COMPLETE: Read packet data field and checksum
78 // TO COMPLETE: When TC complete PUSH tc_buffer into FIFO
79
80 tc_buffer[idx] = data;
81 idx++;
82
83 if(idx == bytes_to_read)
84 {
85 //uint8_t tc_fifo_push(tc_fifo_t *p_tc_fifo, uint8_t *p_data, uint32_t n)
86
87 tc_fifo_push(&tc_fifo, tc_buffer, bytes_to_read); //tc_fifo lo dice la
función//el puntero es nuestro array tc_buffer//El tamaño total es bytes_to_read que ya lo
he calculado antes
88 idx = 0;
89 bytes_to_read = 0;
90 receiver_state = IDLE;
91
92
93 counter = 0; // Se ha recibido el TC completo, desactivamos el contador
94 }
95
96 break;
97 }
98 }
99
100 /*
101 Build TM 17.2 example
102 */
localhost:57236/44e087aa-8d84-458a-b82c-265fdfd2cb1d/ 2/6
10/1/25, 11:36 tm_tc_handling.c
localhost:57236/44e087aa-8d84-458a-b82c-265fdfd2cb1d/ 3/6
10/1/25, 11:36 tm_tc_handling.c
151
152 serialize_uint16(tm_packet_header.packet_id, &tm_bytes[0]);
153 serialize_uint16(tm_packet_header.packet_seq_ctrl, &tm_bytes[2]);
154 serialize_uint16(tm_packet_header.packet_length, &tm_bytes[4]);
155
156 // Store version field into the corresponding byte
157 tm_bytes[6] = df_header.version;
158
159 // Store the remaining fields into their respective locations
160 tm_bytes[7] = df_header.type;
161 tm_bytes[8] = df_header.subtype;
162 tm_bytes[9] = df_header.destinationID;
163
164 // Create app data
165 serialize_uint32(tc_packet_id, &tm_bytes[10]);//El application data entra en la
posicion 10
166
167 uint16_t crc_value = cal_crc_16(tm_bytes, 6+4+4); // 6 bytes CCSDS header, 4
bytes PUS header, 4 application data
168 serialize_uint16(crc_value, &tm_bytes[14]); //Esto es el crc
169
170 return 6+4+4+2; // packet header + pus header + tc_packet_id + checksum
171 }
172
173 uint32_t build_response_tm_1_
2(uint8_t tm_bytes[], uint16_t tm_seq_count, uint16_t
tc_packet_id, uint16_t tc_packet_seq_ctrl, uint8_t error_code)
174 {
175 struct ccds_pus_tmtc_packet
_header tm_packet_header;
176 struct ccds_pus_tm_df_heade
r df_header;
177
178 tm_packet_header.packet_id = ccsds_pus_tm_build_p
acket_id(EPD_APID);
179 tm_packet_header.packet_seq_ctrl = ccsds_pus_tm_build_p
acket_seq_ctrl(0x3,
tm_seq_count); // verify packet sequence (0x3)
180 tm_packet_header.packet_length = 4+4+1+2 - 1; // pus header + application data(Tc
application ID(4) + error(1)) + checksum - 1(convenio)
181
182 df_header.version = 0x10; // 0001 0000
183 df_header.type = 1; //es 1,2 asi que 1
184 df_header.subtype = 2; //es 1,2 asi que 2
185 df_header.destinationID = EPD_DESTINATION_ID; //Es igual en todos
186
187 serialize_uint16(tm_packet_header.packet_id, &tm_bytes[0]);
188 serialize_uint16(tm_packet_header.packet_seq_ctrl, &tm_bytes[2]);
189 serialize_uint16(tm_packet_header.packet_length, &tm_bytes[4]);
190
191 // Store version field into the corresponding byte
192 tm_bytes[6] = df_header.version;
193
194 // Store the remaining fields into their respective locations
195 tm_bytes[7] = df_header.type;
196 tm_bytes[8] = df_header.subtype;
197 tm_bytes[9] = df_header.destinationID;
198
199 // Create app data
localhost:57236/44e087aa-8d84-458a-b82c-265fdfd2cb1d/ 4/6
10/1/25, 11:36 tm_tc_handling.c
localhost:57236/44e087aa-8d84-458a-b82c-265fdfd2cb1d/ 5/6
10/1/25, 11:36 tm_tc_handling.c
localhost:57236/44e087aa-8d84-458a-b82c-265fdfd2cb1d/ 6/6
10/1/25, 11:36 tm_tc_handling.h
1 #ifndef TM_TC_HANDLING_H
2 #define TM_TC_HANDLING_H
3
4 #include "riscv_types.h"
5
6 #define IDLE 0
7 #define READING_CCSDS_HEADER1
8 #define READING_PACKET_DF 2
9
10 #define TC_HEADER_SIZE 6
11
12 void uart_rx_irq_handler(void);
13 void timer_handler(void);
14
15 uint32_t build_response_tm_17
_2(uint8_t tm_bytes[], uint16_t tm_seq_count, uint16_t
tc_packet_id, uint16_t tc_packet_seq_ctrl);
16 uint32_t build_response_tm_1_
1 (uint8_t tm_bytes[], uint16_t tm_seq_count, uint16_t
tc_packet_id, uint16_t tc_packet_seq_ctrl);
17 uint32_t build_response_tm_1_
2 (uint8_t tm_bytes[], uint16_t tm_seq_count, uint16_t
tc_packet_id, uint16_t tc_packet_seq_ctrl, uint8_t error);
18 uint32_t build_response_tm_1_
7 (uint8_t tm_bytes[], uint16_t tm_seq_count, uint16_t
tc_packet_id, uint16_t tc_packet_seq_ctrl);
19 uint32_t build_response_tm_1_
8 (uint8_t tm_bytes[], uint16_t tm_seq_count, uint16_t
tc_packet_id, uint16_t tc_packet_seq_ctrl, uint8_t error);
20
21 void sendTM( uint8_t tm_bytes[], uint32_t n );
22
23 #endif /* TM_TC_HANDLING_H */
24 //[Link] de interrupciones UART (uart_rx_irq_handler)
25 //Estados de recepción:
26 //-----------IDLE: Espera un encabezado CCSDS válido que comience con 0x1B.
27 //-----------READING_CCSDS_HEADER
: Lee el encabezado CCSDS (6 bytes).
28 //-----------READING_PACKET_DF: Lee los datos de la trama y el checksum.
29 //Cálculo de bytes_to_read:
30 //-----------Se basa en el campo packet_length del encabezado CCSDS.
31 //-----------Asegura la lectura completa del paquete, incluyendo los datos y el checksum.
32 //Función tc_fifo_push:
33 //-----------Una vez recibido el paquete completo, lo almacena en un FIFO para su posterior
procesamiento.
34
35 //[Link]ón de tramas TM (build_response_tm_*)
36 //Las funciones crean tramas de telemetría según el tipo/subtipo requerido.
37 //Encabezados CCSDS y PUS:
38 //-----------Se construyen utilizando funciones auxiliares (ccsds_pus_tm_build_p
acket_id,
etc.).
39 //-----------Se serializan en el array tm_bytes para enviarse posteriormente.
40 //Datos de la aplicación:
41 //-----------Algunas TMs incluyen datos específicos, como el tc_packet_id o códigos de error.
42 //Cálculo del CRC:
43 //-----------Utiliza la función cal_crc_16 para asegurar la integridad de los datos
transmitidos.
44
localhost:57236/65885ee9-a59d-4cb7-a666-00ca68ae6700/ 1/2
10/1/25, 11:36 tm_tc_handling.h
45
46 //3. Envío de TMs (sendTM)
47 //Envía cada byte de la trama TM a través de UART.
48 //Gestiona errores potenciales en la transmisión.
49
50
51
localhost:57236/65885ee9-a59d-4cb7-a666-00ca68ae6700/ 2/2