forked from xobs/chumbot
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpwm.c
162 lines (142 loc) · 4.71 KB
/
pwm.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/*
* Author: Michael Ortiz
* Email: [email protected]
*
* Desc: Functions for car pwm signal control. Includes a tuning driver.
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <signal.h>
#define HW_PINCTRL_MUXSEL3 0x80018130
#define HW_PINCTRL_MUXSEL3_SET 0x80018134
#define HW_PINCTRL_MUXSEL3_CLR 0x80018138
#define HW_PWM_CTRL 0x80064000
#define HW_PWM_CTRL_SET 0x80064004
#define HW_PWM_CTRL_CLR 0x80064008
#define HW_PWM_ACTIVE0 0x80064010
#define HW_PWM_PERIOD0 0x80064020
#define HW_PWM_ACTIVE1 0x80064030
#define HW_PWM_PERIOD1 0x80064040
#define HW_PWM_ACTIVE2 0x80064050
#define HW_PWM_PERIOD2 0x80064060
#define HW_PWM_ACTIVE3 0x80064070
#define HW_PWM_PERIOD3 0x80064080
#define HW_PWM_ACTIVE4 0x80064090
#define HW_PWM_PERIOD4 0x800640a0
static int *mem = 0;
static int fd = 0;
static int *prev_mem_range = 0;
/******************************************************************************
* read_kernel_memory
*
* params:
* long offset - the offset of memory location to read
*
* desc:
* this function will return the 4-bytes at the specified
* memory offset of kernel memory
*****************************************************************************/
static int read_kernel_memory(long offset) {
int result;
int *mem_range = (int *)(offset & ~0xFFFF);
if( mem_range != prev_mem_range )
{
prev_mem_range = mem_range;
if(mem)
munmap(mem, 0xFFFF);
if(fd)
close(fd);
fd = open("/dev/mem", O_RDWR);
if( fd < 0 ) {
perror("Unable to open /dev/mem");
fd = 0;
return -1;
}
mem = mmap(0, 0xffff, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset&~0xFFFF);
if( -1 == (int)mem ) {
perror("Unable to mmap file");
if( -1 == close(fd) )
perror("Also couldn't close file");
fd=0;
return -1;
}
}
int scaled_offset = (offset-(offset&~0xFFFF));
result = mem[scaled_offset/sizeof(long)];
return result;
}
/******************************************************************************
* write_kernel_memory
*
* params:
* long offset - the offset of memory location to write
*
* desc:
* this function will write the 4-byte value at the specified
* memory offset of kernel memory
*****************************************************************************/
static int write_kernel_memory(long offset, long value) {
int old_value = read_kernel_memory(offset);
int scaled_offset = (offset-(offset & 0xFFFF0000L));
if(mem)
mem[scaled_offset/sizeof(long)] = value;
return old_value;
}
/******************************************************************************
* pwm_init
*
* params:
* na
*
* desc:
* configures the pwm pins
*****************************************************************************/
int pwm_init()
{
//Change mux to use pins and set to pwm output for PWM3 and PWM4
write_kernel_memory(HW_PINCTRL_MUXSEL3_CLR, 0x3f000000);
write_kernel_memory(HW_PWM_CTRL_SET, 0x0000001c);
return 0;
}
/******************************************************************************
* pwm_turn
*
* params:
* int value - pwm register setting for the "turning" pwm signal
*
* desc:
* sets the "turning" pwm register to the specified value
*****************************************************************************/
int pwm_right(int value)
{
value = (value << 16) & 0xffff0000L;
//fprintf(stderr, "Setting HW_PWM_ACTIVE3: %08x: ", value);
write_kernel_memory(HW_PWM_ACTIVE3, value);
//fprintf(stderr, "%08x\n", read_kernel_memory(HW_PWM_ACTIVE3));
// Divide the 24 MHz crystal by 8, and set a period of 0xea60.
// This will give us a period of 20ms.
write_kernel_memory(HW_PWM_PERIOD3, 0x003bea60);
return 0;
}
/******************************************************************************
* pwm_drive
*
* params:
* int value - pwm register setting for the "drive" pwm signal
*
* desc:
* sets the "drive" pwm register to the specified value
*****************************************************************************/
int pwm_left(int value)
{
//fprintf(stderr, "Setting HW_PWM_ACTIVE4: %08x: ", value<<16);
write_kernel_memory(HW_PWM_ACTIVE2, value << 16);
//fprintf(stderr, "%08x\n", read_kernel_memory(HW_PWM_ACTIVE3));
// Divide the 24 MHz crystal by 8, and set a period of 0xea60.
// This will give us a period of 20ms.
write_kernel_memory(HW_PWM_PERIOD2, 0x003bea60);
return 0;
}