Project

General

Profile

Revision 196

changing stuff to correct labs

View differences:

lab2/utils.h
1
#ifndef UTILS_H_INCLUDED
2
#define UTILS_H_INCLUDED
3

  
4
int(util_get_LSB)(uint16_t val, uint8_t *lsb);
5

  
6
int(util_get_MSB)(uint16_t val, uint8_t *msb);
7

  
8
#ifdef LAB3
9
    uint32_t sys_inb_counter;
10
#endif
11

  
12
int (util_sys_inb)(int port, uint8_t *value);
13

  
14
#endif //UTILS_H_INCLUDED
15 0

  
lab2/i8254.h
1
#ifndef _LCOM_I8254_H_
2
#define _LCOM_I8254_H_
3

  
4
#include <lcom/lcf.h>
5

  
6
/** @defgroup i8254 i8254
7
 * @{
8
 *
9
 * Constants for programming the i8254 Timer. Needs to be completed.
10
 */
11

  
12
#define TIMER_FREQ     1193182 /**< @brief clock frequency for timer in PC and AT */
13
#define TIMER_MIN_FREQ (TIMER_FREQ/UINT16_MAX) + ((TIMER_FREQ % UINT16_MAX) ? 1 : 0) /**< @brief mininum frequency for timer */
14
#define TIMER0_IRQ     0 /**< @brief Timer 0 IRQ line */
15

  
16
/* I/O port addresses */
17

  
18
#define TIMER_0    0x40 /**< @brief Timer 0 count register */
19
#define TIMER_1    0x41 /**< @brief Timer 1 count register */
20
#define TIMER_2    0x42 /**< @brief Timer 2 count register */
21
#define TIMER_CTRL 0x43 /**< @brief Control register */
22

  
23
#define SPEAKER_CTRL 0x61 /**< @brief Register for speaker control  */
24

  
25
/* Timer control */
26

  
27
/* Timer selection: bits 7 and 6 */
28

  
29
#define TIMER_SEL0   0x00              /**< @brief Control Word for Timer 0 */
30
#define TIMER_SEL1   BIT(6)            /**< @brief Control Word for Timer 1 */
31
#define TIMER_SEL2   BIT(7)            /**< @brief Control Word for Timer 2 */
32
#define TIMER_RB_CMD (BIT(7) | BIT(6)) /**< @brief Read Back Command */
33

  
34
/* Register selection: bits 5 and 4 */
35

  
36
#define TIMER_LSB     BIT(4)                  /**< @brief Initialize Counter LSB only */
37
#define TIMER_MSB     BIT(5)                  /**< @brief Initialize Counter MSB only */
38
#define TIMER_LSB_MSB (TIMER_LSB | TIMER_MSB) /**< @brief Initialize LSB first and MSB afterwards */
39
#define TIMER_INMODE_MASK 0x30      //0011 0000
40
#define TIMER_INMODE_POS  4
41

  
42
/* Operating mode: bits 3, 2 and 1 */
43

  
44
#define TIMER_SQR_WAVE (BIT(2) | BIT(1)) /**< @brief Mode 3: square wave generator */
45
#define TIMER_RATE_GEN BIT(2)            /**< @brief Mode 2: rate generator */
46
#define TIMER_MODE_MASK 0x0E             /**< @brief Mask for mode */
47
#define TIMER_MODE_POS  1                /**< @brief Position of smallest bit from mode */
48
#define TIMER_MODE_2ALT 0x6              /**< @brief Alternative notation for mode 2 */
49
#define TIMER_MODE_3ALT 0x7              /**< @brief Alternative notation for mode 3 */
50
#define TIMER_MODE_RED2 0x03             /**< @brief Reduce 3-bit mode to 2-bit mode */
51

  
52
/* Counting mode: bit 0 */
53

  
54
#define TIMER_BCD 0x01 /**< @brief Count in BCD */
55
#define TIMER_BIN 0x00 /**< @brief Count in binary */
56

  
57
/* READ-BACK COMMAND FORMAT */
58

  
59
#define TIMER_RB_COUNT_  BIT(5)
60
#define TIMER_RB_STATUS_ BIT(4)
61
#define TIMER_RB_SEL(n)  BIT((n) + 1)
62

  
63
/**@}*/
64

  
65
#endif /* _LCOM_I8254_H */
66 0

  
lab2/timer.c
1
#include <lcom/lcf.h>
2
#include <lcom/timer.h>
3

  
4
#include <stdint.h>
5

  
6
#include "i8254.h"
7

  
8
int (timer_set_frequency)(uint8_t timer, uint32_t freq) {
9

  
10
    // Frequencies out this range are not supported (by limitation of hardware)
11
    if (freq > TIMER_FREQ || freq < TIMER_MIN_FREQ) {
12
        printf("%s: Frequency out of range, must be between %d and %d.\n", __func__, TIMER_MIN_FREQ, TIMER_FREQ);
13
        return 1;
14
    }
15

  
16
    uint8_t status = 0;
17
    if (timer_get_conf(timer, &status)) return 1;
18
    //Make command
19
    uint8_t write_cmd = 0;
20
    //Select timer
21
    switch(timer) {
22
        case 0: write_cmd |= TIMER_SEL0; break;
23
        case 1: write_cmd |= TIMER_SEL1; break;
24
        case 2: write_cmd |= TIMER_SEL2; break;
25
        default: return 1;
26
    }
27
    //Change both LSB and MSB
28
    write_cmd |= TIMER_LSB_MSB;
29
    //Keep 4 least significant bits
30
    write_cmd |= (status & (TIMER_MODE_MASK | TIMER_BCD));
31
    //Write cmd
32
    if (sys_outb(TIMER_CTRL, write_cmd)) return 1;
33

  
34
    // counter_init = clock/freq
35
    uint16_t counter_init = (uint16_t)(TIMER_FREQ / freq);
36

  
37
    int timer_port = 0;
38
    switch(timer) {
39
        case 0: timer_port = TIMER_0; break;
40
        case 1: timer_port = TIMER_1; break;
41
        case 2: timer_port = TIMER_2; break;
42
        default: return 1;
43
    }
44
    uint8_t lsb = 0, msb = 0;
45
    /* Split the 16 bits word in two bytes */
46
    if (util_get_LSB(counter_init, &lsb)) return 1;
47
    if (util_get_MSB(counter_init, &msb)) return 1;
48

  
49
    /* Write the 8 LSB of the counter */
50
    if (sys_outb(timer_port, lsb)) return 1;
51
    /* Write the 8 MSB of the counter */
52
    if (sys_outb(timer_port, msb)) return 1;
53

  
54
    return 0;
55
}
56

  
57
int hook_id;
58

  
59
int (timer_subscribe_int)(uint8_t *bit_no) {
60
    if(bit_no == NULL) return 1;
61
    hook_id = 2;
62
    *bit_no = hook_id;
63
    /* Subscribe Timer 0 Interrupts */
64
    return sys_irqsetpolicy(TIMER0_IRQ, IRQ_REENABLE, &hook_id);
65
}
66

  
67
int (timer_unsubscribe_int)() {
68
    /* Unsubscribe Timer 0 Interrupts */
69
    if(sys_irqrmpolicy(&hook_id)) return 1;
70
    return 0;
71
}
72

  
73
int no_interrupts = 0;
74
void (timer_int_handler)() {
75
    no_interrupts++;
76
}
77

  
78
int (timer_get_conf)(uint8_t timer, uint8_t *st) {
79
    if(st == NULL) return 1;
80
    // Write read-back command to TIMER_CTRL
81
    u32_t cmd = TIMER_RB_CMD | TIMER_RB_COUNT_ | TIMER_RB_SEL(timer);
82
    if(sys_outb(TIMER_CTRL, cmd)) return 1;
83
    int read_port;
84
    switch(timer) {
85
        case 0: read_port = TIMER_0; break;
86
        case 1: read_port = TIMER_1; break;
87
        case 2: read_port = TIMER_2; break;
88
        default: return 1;
89
    }
90
    if(util_sys_inb(read_port, st)) return 1;
91
    return 0;
92
}
93

  
94
int (timer_display_conf)(uint8_t timer, uint8_t st, enum timer_status_field field) {
95
    union timer_status_field_val conf;
96
    uint8_t in_mode;
97
    switch(field){
98
        case tsf_all:
99
            conf.byte = st; /* Full Status Byte */
100
            break;
101
        case tsf_initial:
102
            /* Counter Initial Value Loading Mode */
103
            in_mode = (st & TIMER_INMODE_MASK) >> TIMER_INMODE_POS;
104
            switch(in_mode){
105
                case 0: conf.in_mode = INVAL_val    ; break; //000
106
                case 1: conf.in_mode = LSB_only     ; break; //001
107
                case 2: conf.in_mode = MSB_only     ; break; //010
108
                case 3: conf.in_mode = MSB_after_LSB; break; //011
109
                default: return 1;
110
            }
111
            break;
112
        case tsf_mode:
113
            /* Counting Mode */
114
            conf.count_mode = (st & TIMER_MODE_MASK)>>TIMER_MODE_POS;
115
            if(conf.count_mode == TIMER_MODE_2ALT || conf.count_mode == TIMER_MODE_3ALT)
116
                conf.count_mode &= TIMER_MODE_RED2;
117
            break;
118
        case tsf_base:
119
            /* Representation of Counter Initial Value */
120
            conf.bcd = st & TIMER_BCD;
121
            break;
122
        default: return 1;
123
    }
124
    if(timer_print_config(timer, field, conf)) return 1;
125
    return 0;
126
}
127 0

  
lab2/utils.c
1
#include <lcom/lcf.h>
2

  
3
#include <stdint.h>
4

  
5
int(util_get_LSB)(uint16_t val, uint8_t *lsb) {
6
    if (lsb == NULL) return 1;
7
    *lsb = val;
8
    return 0;
9
}
10

  
11
int(util_get_MSB)(uint16_t val, uint8_t *msb) {
12
    if (msb == NULL) return 1;
13
    *msb = (val >> 8);
14
    return 0;
15
}
16

  
17
#ifdef LAB3
18
    uint32_t sys_inb_counter = 0;
19
#endif
20

  
21
int (util_sys_inb)(int port, uint8_t *value) {
22
    if(value == NULL) return 1;
23
    uint32_t n = 0;
24
    if(sys_inb(port, &n)) return 1;
25
    *value = n;
26
    #ifdef LAB3
27
        ++sys_inb_counter;
28
    #endif
29
    return 0;
30
}
31 0

  
lab2/lab2.c
1
#include <lcom/lcf.h>
2
#include <lcom/lab2.h>
3

  
4
#include <stdbool.h>
5
#include <stdint.h>
6

  
7
int main(int argc, char *argv[]) {
8
  // sets the language of LCF messages (can be either EN-US or PT-PT)
9
  lcf_set_language("EN-US");
10

  
11
  // enables to log function invocations that are being "wrapped" by LCF
12
  // [comment this out if you don't want/need it]
13
  lcf_trace_calls("/home/lcom/labs/lab2/trace.txt");
14

  
15
  // enables to save the output of printf function calls on a file
16
  // [comment this out if you don't want/need it]
17
  lcf_log_output("/home/lcom/labs/lab2/output.txt");
18

  
19
  // handles control over to LCF
20
  // [LCF handles command line arguments and invokes the right function]
21
  if (lcf_start(argc, argv))
22
    return 1;
23

  
24
  // LCF clean up tasks
25
  // [must be the last statement before return]
26
  lcf_cleanup();
27

  
28
  return 0;
29
}
30

  
31
int(timer_test_read_config)(uint8_t timer, enum timer_status_field field){
32
    uint8_t state = 0;
33
    if(timer_get_conf(timer, &state)) return 1;
34
    if(timer_display_conf(timer, state, field)) return 1;
35
    return 0;
36
}
37

  
38
int(timer_test_time_base)(uint8_t timer, uint32_t freq) {
39
    if (timer_set_frequency(timer, freq)) return 1;
40
    return 0;
41
}
42

  
43
extern int no_interrupts;
44

  
45
int(timer_test_int)(uint8_t time) {
46
    const int frequency = 60; // Frequency asummed at 60Hz
47
    int ipc_status, r;
48
    message msg;
49
    uint8_t timer_id = 0;
50
    no_interrupts = 0;
51
    if (timer_subscribe_int(&timer_id)) return 1;
52
    int irq_set = BIT(timer_id);
53
    while (time) {
54
        /* Get a request message. */
55
        if ((r = driver_receive(ANY, &msg, &ipc_status)) != 0) {
56
            printf("driver_receive failed with %d", r);
57
            continue;
58
        }
59
        if (is_ipc_notify(ipc_status)) { /* received notification */
60
            switch (_ENDPOINT_P(msg.m_source)) {
61
                case HARDWARE: /* hardware interrupt notification */
62
                    if (msg.m_notify.interrupts & irq_set) { /* subscribed interrupt */
63
                        timer_int_handler();
64
                        if (!(no_interrupts % frequency)) { /* second elapsed */
65
                            timer_print_elapsed_time();
66
                            time--;
67
                        }
68
                    }
69
                    break;
70
                default:
71
                    break; /* no other notifications expected: do nothing */
72
            }
73
        } else { /* received standart message, not a notification */
74
            /* no standart message expected: do nothing */
75
        }
76
    }
77
    if (timer_unsubscribe_int()) return 1;
78
    return 0;
79
}
80 0

  
lab2/include/errors.h
1
#ifndef ERRORS_H_INCLUDED
2
#define ERRORS_H_INCLUDED
3

  
4
/** @brief Error Codes */
5
enum errors {
6
    SUCCESS = 0,        /** @brief Sucessful */
7
    NULL_PTR,           /** @brief Null Pointer Error */
8
    LCF_ERROR,          /** @brief Error originated on LCF */
9
    SBCR_ERROR,         /** @brief Error on Subscribing Interrupt */
10
    UNSBCR_ERROR,       /** @brief Error on Unsubscring Interrupt*/
11
    READ_ERROR,         /** @brief Error on Reading from Port */
12
    WRITE_ERROR,        /** @brief Error on Writing to Port */
13
    TIMEOUT_ERROR,      /** @brief Timeout error */
14
    INVALID_COMMAND,    /** @brief Invalid Command issued */
15
    INVALID_STATE,      /** @brief State machine reached an invalid state */
16
    BIOS_CALL_ERROR,    /** @brief Error upon BIOS call */
17
    OUT_OF_RANGE,       /** @brief Accessing area out of range of memory */
18
    ALLOC_ERROR,        /** @brief Memory allocation error */
19
    LOGIC_ERROR,        /** @brief Logic error */
20
    OTHER_ERROR         /** @brief Unspecified error */
21
};
22

  
23
#endif //ERRORS_H_INCLUDED
0 24

  
lab2/include/i8254.h
1
#ifndef _LCOM_I8254_H_
2
#define _LCOM_I8254_H_
3

  
4
/** @defgroup i8254 i8254
5
 *
6
 * Constants for programming the i8254 Timer. Needs to be completed.
7
 */
8

  
9
#define TIMER_FREQ     1193182                                                          /**< @brief clock frequency for timer in PC and AT */
10
#define TIMER_MIN_FREQ (TIMER_FREQ/UINT16_MAX) + ((TIMER_FREQ % UINT16_MAX) ? 1 : 0)    /**< @brief mininum frequency for timer */
11
#define TIMER0_IRQ     0                                                                /**< @brief Timer 0 IRQ line */
12

  
13
/* I/O port addresses */
14

  
15
#define TIMER_0    0x40         /**< @brief Timer 0 count register */
16
#define TIMER_1    0x41         /**< @brief Timer 1 count register */
17
#define TIMER_2    0x42         /**< @brief Timer 2 count register */
18
#define TIMER_CTRL 0x43         /**< @brief Control register */
19

  
20
#define SPEAKER_CTRL 0x61       /**< @brief Register for speaker control  */
21

  
22
/* Timer control */
23

  
24
/* Timer selection: bits 7 and 6 */
25

  
26
#define TIMER_SEL0   0x00              /**< @brief Control Word for Timer 0 */
27
#define TIMER_SEL1   BIT(6)            /**< @brief Control Word for Timer 1 */
28
#define TIMER_SEL2   BIT(7)            /**< @brief Control Word for Timer 2 */
29
#define TIMER_RB_CMD (BIT(7) | BIT(6)) /**< @brief Read Back Command */
30

  
31
/* Register selection: bits 5 and 4 */
32

  
33
#define TIMER_LSB     BIT(4)                    /**< @brief Initialize Counter LSB only */
34
#define TIMER_MSB     BIT(5)                    /**< @brief Initialize Counter MSB only */
35
#define TIMER_LSB_MSB (TIMER_LSB | TIMER_MSB)   /**< @brief Initialize LSB first and MSB afterwards */
36
#define TIMER_INMODE_MASK 0x30                  /**< @brief Mask for Timer Counter Mode */
37
#define TIMER_INMODE_POS  4                     /**< @brief Bit position of Timer Counter Mode */
38

  
39
/* Operating mode: bits 3, 2 and 1 */
40

  
41
#define TIMER_SQR_WAVE (BIT(2) | BIT(1)) /**< @brief Mode 3: square wave generator */
42
#define TIMER_RATE_GEN BIT(2)            /**< @brief Mode 2: rate generator */
43
#define TIMER_MODE_MASK 0x0E             /**< @brief Mask for mode */
44
#define TIMER_MODE_POS  1                /**< @brief Position of smallest bit from mode */
45
#define TIMER_MODE_2ALT 0x6              /**< @brief Alternative notation for mode 2 */
46
#define TIMER_MODE_3ALT 0x7              /**< @brief Alternative notation for mode 3 */
47
#define TIMER_MODE_RED2 0x03             /**< @brief Reduce 3-bit mode to 2-bit mode */
48

  
49
/* Counting mode: bit 0 */
50

  
51
#define TIMER_BCD 0x01 /**< @brief Count in BCD */
52
#define TIMER_BIN 0x00 /**< @brief Count in binary */
53

  
54
/* READ-BACK COMMAND FORMAT */
55

  
56
#define TIMER_RB_COUNT_  BIT(5)         /**< @brief Read counter value on read-back (0 to activate) */
57
#define TIMER_RB_STATUS_ BIT(4)         /**< @brief Read status value on read-back (0 to activate) */
58
#define TIMER_RB_SEL(n)  BIT((n) + 1)   /**< @brief Select timer to read information from */
59

  
60
/**@}*/
61

  
62
#endif /* _LCOM_I8254_H */
0 63

  
lab2/include/timer.h
1
/**
2
 * This file concerns everything related to the timer
3
 */
4

  
5
#ifndef TIMER_H_INCLUDED
6
#define TIMER_H_INCLUDED
7

  
8
//7.1 timer_test_read_config()
9
int (timer_get_conf)(uint8_t timer, uint8_t *st);
10
int (timer_display_conf)(uint8_t timer, uint8_t st, enum timer_status_field field);
11
//7.2 timer_test_time_base()
12
int (timer_set_frequency)(uint8_t timer, uint32_t freq);
13
//7.3 timer_test_int()
14
void (timer_int_handler)(void);
15
int (subscribe_timer_interrupt)(uint8_t interrupt_bit, int *interrupt_id);
16
uint32_t no_interrupts;
17

  
18
#endif //TIMER_H_INCLUDED
0 19

  
lab2/include/utils.h
1
#ifndef UTILS_H_INCLUDED
2
#define UTILS_H_INCLUDED
3

  
4
/**
5
 * @brief Gets the least significant byte of a 16-bit variable
6
 * @param val 16-bit variable
7
 * @param lsb Pointer to a 8-bit variable to store the value of the LSB
8
 * @return ERROR_CODE code representing the result of the operation, SUCCESS code is returned if everything is OK
9
 */
10
int(util_get_LSB)(uint16_t val, uint8_t *lsb);
11

  
12
/**
13
 * @brief Gets the most significant byte of a 16-bit variable
14
 * @param val 16-bit variable
15
 * @param lsb Pointer to a 8-bit variable to store the value of the MSB
16
 * @return ERROR_CODE code representing the result of the operation, SUCCESS code is returned if everything is OK
17
 */
18
int(util_get_MSB)(uint16_t val, uint8_t *msb);
19

  
20
/**
21
 * @brief sys_inb wrapper
22
 * @param port Port to read from
23
 * @param value Pointer to byte to store value read
24
 * @return ERROR_CODE code representing the result of the operation, SUCCESS code is returned if everything is OK
25
 */
26
int (util_sys_inb)(int port, uint8_t *value);
27

  
28
/**
29
 * @brief Unsubcribes Interrupts
30
 * @param interrupt_id Interrupt ID, value via arguments on subscription of the interrupt_id
31
 * @see subscribe_kbc_interrupt, subscribe_timer_interrupt
32
 * @return ERROR_CODE code representing the result of the operation, SUCCESS code is returned if everything is OK
33
 */
34
int (unsubscribe_interrupt)(int *interrupt_id);
35

  
36
/**
37
 * @brief Gets the minimum value out of two values.
38
 * @param a     First value
39
 * @param b     Second value
40
 * @return  The minimum of the two values
41
 */
42
int32_t min(int32_t a, int32_t b);
43

  
44
/**
45
 * @brief Gets the maximum value out of two values.
46
 * @param a     First value
47
 * @param b     Second value
48
 * @return  The maximum of the two values
49
 */
50
int32_t max(int32_t a, int32_t b);
51

  
52

  
53
#endif //UTILS_H_INCLUDED
0 54

  
lab2/src/lab2.c
1
#include <lcom/lcf.h>
2
#include <lcom/lab2.h>
3

  
4
#include <stdbool.h>
5
#include <stdint.h>
6

  
7
#include "timer.h"
8

  
9
int main(int argc, char *argv[]) {
10
  // sets the language of LCF messages (can be either EN-US or PT-PT)
11
  lcf_set_language("EN-US");
12

  
13
  // enables to log function invocations that are being "wrapped" by LCF
14
  // [comment this out if you don't want/need it]
15
  lcf_trace_calls("/home/lcom/labs/lab2/trace.txt");
16

  
17
  // enables to save the output of printf function calls on a file
18
  // [comment this out if you don't want/need it]
19
  lcf_log_output("/home/lcom/labs/lab2/output.txt");
20

  
21
  // handles control over to LCF
22
  // [LCF handles command line arguments and invokes the right function]
23
  if (lcf_start(argc, argv))
24
    return 1;
25

  
26
  // LCF clean up tasks
27
  // [must be the last statement before return]
28
  lcf_cleanup();
29

  
30
  return 0;
31
}
32

  
33
int(timer_test_read_config)(uint8_t timer, enum timer_status_field field){
34
    uint8_t state = 0;
35
    if(timer_get_conf(timer, &state)) return 1;
36
    if(timer_display_conf(timer, state, field)) return 1;
37
    return 0;
38
}
39

  
40
int(timer_test_time_base)(uint8_t timer, uint32_t freq) {
41
    if (timer_set_frequency(timer, freq)) return 1;
42
    return 0;
43
}
44

  
45
int(timer_test_int)(uint8_t time) {
46
    const int frequency = 60; // Frequency asummed at 60Hz
47
    int ipc_status, r;
48
    message msg;
49
    uint8_t timer_id = 0;
50
    no_interrupts = 0;
51
    if (timer_subscribe_int(&timer_id)) return 1;
52
    int irq_set = BIT(timer_id);
53
    while (time) {
54
        /* Get a request message. */
55
        if ((r = driver_receive(ANY, &msg, &ipc_status)) != 0) {
56
            printf("driver_receive failed with %d", r);
57
            continue;
58
        }
59
        if (is_ipc_notify(ipc_status)) { /* received notification */
60
            switch (_ENDPOINT_P(msg.m_source)) {
61
                case HARDWARE: /* hardware interrupt notification */
62
                    if (msg.m_notify.interrupts & irq_set) { /* subscribed interrupt */
63
                        timer_int_handler();
64
                        if (!(no_interrupts % frequency)) { /* second elapsed */
65
                            timer_print_elapsed_time();
66
                            time--;
67
                        }
68
                    }
69
                    break;
70
                default:
71
                    break; /* no other notifications expected: do nothing */
72
            }
73
        } else { /* received standart message, not a notification */
74
            /* no standart message expected: do nothing */
75
        }
76
    }
77
    if (timer_unsubscribe_int()) return 1;
78
    return 0;
79
}
0 80

  
lab2/src/timer.c
1
#include <lcom/lcf.h>
2

  
3
#include "timer.h"
4

  
5
#include "i8254.h"
6
#include "utils.h"
7
#include "errors.h"
8

  
9
//7.1 timer_test_read_config()
10
int (timer_get_conf)(uint8_t timer, uint8_t *st) {
11
    if(st == NULL) return 1;
12
    // Write read-back command to TIMER_CTRL
13
    u32_t cmd = TIMER_RB_CMD | TIMER_RB_COUNT_ | TIMER_RB_SEL(timer);
14
    if(sys_outb(TIMER_CTRL, cmd)) return 1;
15
    int read_port;
16
    switch(timer) {
17
        case 0: read_port = TIMER_0; break;
18
        case 1: read_port = TIMER_1; break;
19
        case 2: read_port = TIMER_2; break;
20
        default: return 1;
21
    }
22
    if(util_sys_inb(read_port, st)) return 1;
23
    return 0;
24
}
25
int (timer_display_conf)(uint8_t timer, uint8_t st, enum timer_status_field field) {
26
    union timer_status_field_val conf;
27
    uint8_t in_mode;
28
    switch(field){
29
        case tsf_all:
30
            conf.byte = st; /* Full Status Byte */
31
            break;
32
        case tsf_initial:
33
            /* Counter Initial Value Loading Mode */
34
            in_mode = (st & TIMER_INMODE_MASK) >> TIMER_INMODE_POS;
35
            switch(in_mode){
36
                case 0: conf.in_mode = INVAL_val    ; break; //000
37
                case 1: conf.in_mode = LSB_only     ; break; //001
38
                case 2: conf.in_mode = MSB_only     ; break; //010
39
                case 3: conf.in_mode = MSB_after_LSB; break; //011
40
                default: return 1;
41
            }
42
            break;
43
        case tsf_mode:
44
            /* Counting Mode */
45
            conf.count_mode = (st & TIMER_MODE_MASK)>>TIMER_MODE_POS;
46
            if(conf.count_mode == TIMER_MODE_2ALT || conf.count_mode == TIMER_MODE_3ALT)
47
                conf.count_mode &= TIMER_MODE_RED2;
48
            break;
49
        case tsf_base:
50
            /* Representation of Counter Initial Value */
51
            conf.bcd = st & TIMER_BCD;
52
            break;
53
        default: return 1;
54
    }
55
    if(timer_print_config(timer, field, conf)) return 1;
56
    return 0;
57
}
58
//7.2 timer_test_time_base()
59
int (timer_set_frequency)(uint8_t timer, uint32_t freq) {
60

  
61
    // Frequencies out this range are not supported (by limitation of hardware)
62
    if (freq > TIMER_FREQ || freq < TIMER_MIN_FREQ) {
63
        printf("%s: Frequency out of range, must be between %d and %d.\n", __func__, TIMER_MIN_FREQ, TIMER_FREQ);
64
        return 1;
65
    }
66

  
67
    uint8_t status = 0;
68
    if (timer_get_conf(timer, &status)) return 1;
69
    //Make command
70
    uint8_t write_cmd = 0;
71
    //Select timer
72
    switch(timer) {
73
        case 0: write_cmd |= TIMER_SEL0; break;
74
        case 1: write_cmd |= TIMER_SEL1; break;
75
        case 2: write_cmd |= TIMER_SEL2; break;
76
        default: return 1;
77
    }
78
    //Change both LSB and MSB
79
    write_cmd |= TIMER_LSB_MSB;
80
    //Keep 4 least significant bits
81
    write_cmd |= (status & (TIMER_MODE_MASK | TIMER_BCD));
82
    //Write cmd
83
    if (sys_outb(TIMER_CTRL, write_cmd)) return 1;
84

  
85
    // counter_init = clock/freq
86
    uint16_t counter_init = (uint16_t)(TIMER_FREQ / freq);
87

  
88
    int timer_port = 0;
89
    switch(timer) {
90
        case 0: timer_port = TIMER_0; break;
91
        case 1: timer_port = TIMER_1; break;
92
        case 2: timer_port = TIMER_2; break;
93
        default: return 1;
94
    }
95
    uint8_t lsb = 0, msb = 0;
96
    /* Split the 16 bits word in two bytes */
97
    if (util_get_LSB(counter_init, &lsb)) return 1;
98
    if (util_get_MSB(counter_init, &msb)) return 1;
99

  
100
    /* Write the 8 LSB of the counter */
101
    if (sys_outb(timer_port, lsb)) return 1;
102
    /* Write the 8 MSB of the counter */
103
    if (sys_outb(timer_port, msb)) return 1;
104

  
105
    return 0;
106
}
107
//7.3 timer_test_int()
108
void (timer_int_handler)(void) {
109
    no_interrupts++;
110
}
111
#ifdef LAB2
112
    static int hook_id;
113
    int (timer_subscribe_int)(uint8_t *bit_no) {
114
        if(bit_no == NULL) return NULL_PTR;
115
        hook_id = 2;
116
        *bit_no = hook_id;
117
        return sys_irqsetpolicy(TIMER0_IRQ, IRQ_REENABLE, &hook_id);
118
    }
119
    int (timer_unsubscribe_int)() {
120
        return unsubscribe_interrupt(&hook_id);
121
    }
122
#endif
123
int (subscribe_timer_interrupt)(uint8_t interrupt_bit, int *interrupt_id) {
124
    if (interrupt_id == NULL) return 1;
125
    *interrupt_id = interrupt_bit;
126
    return (sys_irqsetpolicy(TIMER0_IRQ, IRQ_REENABLE, interrupt_id));
127
}
128
uint32_t no_interrupts = 0;
0 129

  
lab2/src/utils.c
1
#include <lcom/lcf.h>
2

  
3
#include "utils.h"
4

  
5
#include <stdint.h>
6
#include "errors.h"
7

  
8
int(util_get_LSB)(uint16_t val, uint8_t *lsb) {
9
    if (lsb == NULL) return NULL_PTR;
10
    *lsb = val;
11
    return SUCCESS;
12
}
13

  
14
int(util_get_MSB)(uint16_t val, uint8_t *msb) {
15
    if (msb == NULL) return NULL_PTR;
16
    *msb = (val >> 8);
17
    return SUCCESS;
18
}
19

  
20
int (util_sys_inb)(int port, uint8_t *value) {
21
    if(value == NULL) return NULL_PTR;
22
    uint32_t n = 0;
23
    if(sys_inb(port, &n)) return READ_ERROR;
24
    *value = n;
25
    return SUCCESS;
26
}
27

  
28
int (unsubscribe_interrupt)(int *interrupt_id) {
29
    if (interrupt_id == NULL) return NULL_PTR;
30
    if(sys_irqrmpolicy(interrupt_id)) return UNSBCR_ERROR;
31
    return SUCCESS;
32
}
33

  
34
int32_t min(int32_t a, int32_t b){ return (b < a ? b : a); }
35
int32_t max(int32_t a, int32_t b){ return (a < b ? b : a); }
0 36

  
lab2/Makefile
1 1
# name of the program (Minix service)
2
PROG=lab2 
2
PROG=lab2
3 3

  
4
.PATH: ${.CURDIR}/src
5

  
4 6
# source code files to be compiled
5 7
SRCS = lab2.c timer.c utils.c
6 8

  
7 9
# additional compilation flags
8 10
# "-Wall -Wextra -Werror -I . -std=c11 -Wno-unused-parameter" are already set
9
CFLAGS += -pedantic
11
CFLAGS += -pedantic -I./include -D LAB2
10 12

  
11 13
# list of library dependencies (for Lab 2, only LCF library)
12 14
DPADD += ${LIBLCF}

Also available in: Unified diff