Compare commits
No commits in common. "18a89741e026cee1d5ee6b3be32e391182e8e011" and "4889a5fdfe287a8765f04439fb5511ba65eda109" have entirely different histories.
18a89741e0
...
4889a5fdfe
|
@ -3,12 +3,15 @@
|
||||||
#include "inc/msp432p401r.h"
|
#include "inc/msp432p401r.h"
|
||||||
|
|
||||||
void BumpInit(void) {
|
void BumpInit(void) {
|
||||||
|
// Port 4 pins 0, 2, 3, 5, 6, 7
|
||||||
|
// and enables internal resistors
|
||||||
P4->SEL0 &= ~BUMP_PINS;
|
P4->SEL0 &= ~BUMP_PINS;
|
||||||
P4->SEL1 &= ~BUMP_PINS; // configure P4.0 P4.2 P4.3 P4.5 P4.6 P4.7 as gpio
|
P4->SEL1 &= ~BUMP_PINS; // 1) configure P4.0 P4.2 P4.3 P4.5 P4.6 P4.7 as gpio
|
||||||
P4->DIR &= ~BUMP_PINS; // configure as input
|
P4->DIR &= ~BUMP_PINS; // 2) configure as input
|
||||||
P4->REN |= BUMP_PINS; // enable pull resisors
|
P4->REN |= BUMP_PINS; // 3) enable pull resisors
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t BumpRead(void) {
|
uint8_t BumpRead(void) {
|
||||||
|
// write this as part of Lab 2
|
||||||
return P4->IN;
|
return P4->IN;
|
||||||
}
|
}
|
191
common/rtos.c
191
common/rtos.c
|
@ -1,191 +0,0 @@
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "rtos.h"
|
|
||||||
|
|
||||||
#include "clock.h"
|
|
||||||
#include "cpu.h"
|
|
||||||
#include "timer_a1.h"
|
|
||||||
|
|
||||||
#include "inc/msp432p401r.h"
|
|
||||||
|
|
||||||
#define THREADS 2
|
|
||||||
#define PERIODIC_THREADS 2
|
|
||||||
#define STACKSIZE 100
|
|
||||||
|
|
||||||
typedef struct Tcb {
|
|
||||||
int32_t* sp; // stack pointer
|
|
||||||
struct Tcb* next; // linked-list
|
|
||||||
int32_t* blocked; // shows on which semaphore it is blocked
|
|
||||||
int32_t sleep;
|
|
||||||
} Tcb_t;
|
|
||||||
|
|
||||||
PeriodicEvent_t periodic_event_threads[PERIODIC_THREADS];
|
|
||||||
|
|
||||||
Tcb_t tcbs[THREADS];
|
|
||||||
Tcb_t* run_pt;
|
|
||||||
int32_t stacks[THREADS][STACKSIZE];
|
|
||||||
|
|
||||||
void RunPeriodicEvents(void);
|
|
||||||
|
|
||||||
void __attribute__((naked)) SysTick_Handler(void) {
|
|
||||||
__asm volatile (
|
|
||||||
"CPSID I \n" // disable interrupts
|
|
||||||
"PUSH {R4-R11} \n" // save R4-R11
|
|
||||||
"LDR R0, =run_pt \n" // R0 = pointer to run_pt
|
|
||||||
|
|
||||||
"LDR R1, [R0] \n" // R1 = run_pt
|
|
||||||
"STR SP, [R1] \n" // save current SP
|
|
||||||
|
|
||||||
"PUSH {R0, LR} \n" // save R0, LR
|
|
||||||
"BL Scheduler \n" // call scheduler
|
|
||||||
"POP {R0, LR} \n" // restore R0, LR
|
|
||||||
|
|
||||||
"LDR R1, [R0] \n" // R1 = run_pt
|
|
||||||
"LDR SP, [R1] \n" // restore new SP
|
|
||||||
|
|
||||||
"POP {R4-R11} \n" // restore R4-R11
|
|
||||||
"CPSIE I \n" // enable interrupts
|
|
||||||
"BX LR \n" // exit exception
|
|
||||||
".align 4 \n"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void __attribute__((naked))
|
|
||||||
StartOS(void) {
|
|
||||||
__asm volatile (
|
|
||||||
"LDR R0, =run_pt \n" // address of run_pt
|
|
||||||
"LDR R1, [R0] \n" // R1 = run_pt
|
|
||||||
"LDR SP, [R1] \n" // SP = run_pt->sp
|
|
||||||
|
|
||||||
"POP {R4-R11} \n" // restore R4-R11
|
|
||||||
"POP {R0-R3} \n" // restore R0-R3
|
|
||||||
"POP {R12} \n" // restore R12
|
|
||||||
"ADD SP, SP, #4 \n" // skip LR
|
|
||||||
"POP {LR} \n" // load thread start address
|
|
||||||
"ADD SP, SP, #4 \n" // skip PSR
|
|
||||||
|
|
||||||
"CPSIE I \n" // enable interrupts
|
|
||||||
"BX LR \n" // start thread
|
|
||||||
".align 4 \n"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void SetInitialStack(int i) {
|
|
||||||
tcbs[i].sp = &stacks[i][STACKSIZE-16];
|
|
||||||
stacks[i][STACKSIZE-1] = 0x01000000; // xPSR thumb bit
|
|
||||||
|
|
||||||
stacks[i][STACKSIZE-16] = 16; // R4
|
|
||||||
stacks[i][STACKSIZE-15] = 15; // R5
|
|
||||||
stacks[i][STACKSIZE-14] = 14; // R6
|
|
||||||
stacks[i][STACKSIZE-13] = 13; // R7
|
|
||||||
stacks[i][STACKSIZE-12] = 12; // R8
|
|
||||||
stacks[i][STACKSIZE-11] = 11; // R9
|
|
||||||
stacks[i][STACKSIZE-10] = 10; // R10
|
|
||||||
stacks[i][STACKSIZE-9] = 9; // R11
|
|
||||||
stacks[i][STACKSIZE-8] = 8; // R0
|
|
||||||
stacks[i][STACKSIZE-7] = 7; // R1
|
|
||||||
stacks[i][STACKSIZE-6] = 6; // R2
|
|
||||||
stacks[i][STACKSIZE-5] = 5; // R3
|
|
||||||
stacks[i][STACKSIZE-4] = 4; // R12
|
|
||||||
stacks[i][STACKSIZE-3] = 0; // LR (0 causes fault if thread returns)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize operating system, disable interrupts
|
|
||||||
// Initialize OS controlled I/O: systick, bus clock as fast as possible
|
|
||||||
void RoundRobinInit(void) {
|
|
||||||
CPU_cpsid();
|
|
||||||
ClockInit48MHz();
|
|
||||||
// Write TimerA1Init here 1000 Hz
|
|
||||||
}
|
|
||||||
|
|
||||||
void AddThreads(void (**threads)(void)) {
|
|
||||||
uint32_t i = 0;
|
|
||||||
for (; i < THREADS; ++i) {
|
|
||||||
SetInitialStack(i);
|
|
||||||
stacks[i][STACKSIZE-2] = (int32_t)threads[i];
|
|
||||||
tcbs[i].next = &tcbs[ (i+1) % THREADS ];
|
|
||||||
tcbs[i].blocked = 0;
|
|
||||||
tcbs[i].sleep = 0;
|
|
||||||
// tcbs[i].priority = p0;
|
|
||||||
}
|
|
||||||
run_pt = &tcbs[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
void AddPeriodicEventThreads(PeriodicEvent_t *periodic_events) {
|
|
||||||
uint32_t i = 0;
|
|
||||||
for (;i < PERIODIC_THREADS; ++i) {
|
|
||||||
periodic_event_threads[i] = periodic_events[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RoundRobinLaunch(uint32_t time_slice_cycles) {
|
|
||||||
SysTick->CTRL = 0; // 1) disable SysTick during setup
|
|
||||||
SysTick->LOAD = time_slice_cycles - 1; // 2) reload value sets period
|
|
||||||
SysTick->VAL = 0; // 3) any write to current clears it
|
|
||||||
SCB->SHP[11] = 7 << 5; // set priority into top 3 bits of 8-bit register
|
|
||||||
SysTick->CTRL = 0x00000007; // 4) enable SysTick with core clock and interrupts
|
|
||||||
|
|
||||||
TimerA1Init(RunPeriodicEvents, 5000); // 100Hz
|
|
||||||
StartOS(); // start on the first task
|
|
||||||
}
|
|
||||||
|
|
||||||
void RunPeriodicEvents(void) {
|
|
||||||
int32_t i;
|
|
||||||
for (i = 0; i < THREADS; ++i) {
|
|
||||||
if (tcbs[i].sleep) {
|
|
||||||
--(tcbs[i].sleep);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (i = 0; i < PERIODIC_THREADS; ++i) {
|
|
||||||
periodic_event_threads[i].event();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scheduler(void) {
|
|
||||||
Tcb_t* t = run_pt->next;
|
|
||||||
while (t->blocked || t->sleep) {
|
|
||||||
t = t->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
run_pt = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Suspend(void) {
|
|
||||||
SysTick->VAL = 0; // clear
|
|
||||||
SCB->ICSR |= SCB_ICSR_PENDSTSET_Msk; // trigger
|
|
||||||
}
|
|
||||||
|
|
||||||
void Sleep(int32_t time) {
|
|
||||||
run_pt->sleep = time;
|
|
||||||
Suspend();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decrement semaphore
|
|
||||||
void Wait(int32_t *sema_pt) {
|
|
||||||
CPU_cpsid();
|
|
||||||
--(*sema_pt);
|
|
||||||
if((*sema_pt) < 0) {
|
|
||||||
run_pt->blocked = sema_pt; // reason it is blocked
|
|
||||||
|
|
||||||
CPU_cpsie();
|
|
||||||
Suspend();
|
|
||||||
}
|
|
||||||
CPU_cpsie();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Increment semaphore
|
|
||||||
void Signal(int32_t *sema_pt) {
|
|
||||||
Tcb_t *pt;
|
|
||||||
CPU_cpsid();
|
|
||||||
++(*sema_pt);
|
|
||||||
if ((*sema_pt) <= 0) {
|
|
||||||
pt = run_pt->next;
|
|
||||||
while(pt->blocked != sema_pt) {
|
|
||||||
pt = pt->next;
|
|
||||||
}
|
|
||||||
pt->blocked = 0;
|
|
||||||
}
|
|
||||||
CPU_cpsie();
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
#ifndef RTOS_H
|
|
||||||
#define RTOS_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
typedef struct PeriodicEvent {
|
|
||||||
void (*event)(void);
|
|
||||||
uint32_t period_ms;
|
|
||||||
} PeriodicEvent_t;
|
|
||||||
|
|
||||||
void RoundRobinInit(void);
|
|
||||||
void AddThreads(void (**threads)(void));
|
|
||||||
void AddPeriodicEventThreads(PeriodicEvent_t *periodic_events);
|
|
||||||
void RoundRobinLaunch(uint32_t time_slice_cycles);
|
|
||||||
void Sleep(int32_t time);
|
|
||||||
void Wait(int32_t *sema_pt);
|
|
||||||
void Signal(int32_t *sema_pt);
|
|
||||||
|
|
||||||
#endif /* RTOS_H */
|
|
|
@ -1,77 +0,0 @@
|
||||||
CC = arm-none-eabi-gcc
|
|
||||||
|
|
||||||
# The location of the C compiler
|
|
||||||
# ARMGCC_ROOT is used by some makefiles that need to know where the compiler
|
|
||||||
# is installed.
|
|
||||||
ARMGCC_BIN := ${shell which ${CC}}
|
|
||||||
ifeq (${shell test -h ${ARMGCC_BIN} && echo "true" || echo "false"}, true)
|
|
||||||
ARMGCC_ROOT := ${shell dirname ${shell readlink ${ARMGCC_BIN}}}/..
|
|
||||||
else
|
|
||||||
ARMGCC_ROOT := ${shell dirname ${ARMGCC_BIN}}/..
|
|
||||||
endif
|
|
||||||
|
|
||||||
# Search for source files that are not in this directory
|
|
||||||
VPATH = ../common/
|
|
||||||
|
|
||||||
OBJECTS = main.o rtos.o timer_a1.o bump.o reflectance.o delay.o motor.o pwm.o cpu.o clock.o system.o startup.o syscalls.o
|
|
||||||
|
|
||||||
NAME = lab
|
|
||||||
|
|
||||||
CFLAGS = -I.. -I../inc -I../common \
|
|
||||||
-D__MSP432P401R__ \
|
|
||||||
-DDeviceFamily_MSP432P401x \
|
|
||||||
-mcpu=cortex-m4 \
|
|
||||||
-march=armv7e-m \
|
|
||||||
-mthumb \
|
|
||||||
-std=c99 \
|
|
||||||
-mfloat-abi=hard \
|
|
||||||
-mfpu=fpv4-sp-d16 \
|
|
||||||
-ffunction-sections \
|
|
||||||
-fdata-sections \
|
|
||||||
-gstrict-dwarf \
|
|
||||||
-Wall \
|
|
||||||
-I$(ARMGCC_ROOT)/arm-none-eabi/include/newlib-nano \
|
|
||||||
-I$(ARMGCC_ROOT)/arm-none-eabi/include
|
|
||||||
|
|
||||||
LFLAGS = -Wl,-T,../config.lds \
|
|
||||||
-Wl,-Map,$(NAME).map \
|
|
||||||
-march=armv7e-m \
|
|
||||||
-mthumb \
|
|
||||||
-mfloat-abi=hard \
|
|
||||||
-mfpu=fpv4-sp-d16 \
|
|
||||||
-static \
|
|
||||||
-Wl,--gc-sections \
|
|
||||||
-lgcc \
|
|
||||||
-lc \
|
|
||||||
-lm \
|
|
||||||
-lnosys \
|
|
||||||
--specs=nano.specs
|
|
||||||
|
|
||||||
all: $(NAME).out
|
|
||||||
@echo "SUCCESS: Compilation completed successfully."
|
|
||||||
|
|
||||||
%.o: %.c
|
|
||||||
@$(CC) $(CFLAGS) -g $< -c -o $@
|
|
||||||
|
|
||||||
cpu.o: ../common/cpu.c
|
|
||||||
@$(CC) $(CFLAGS) $< -c -o $@
|
|
||||||
|
|
||||||
clock.o: ../common/clock.c
|
|
||||||
@$(CC) $(CFLAGS) $< -c -o $@
|
|
||||||
|
|
||||||
system.o: ../system.c
|
|
||||||
@$(CC) $(CFLAGS) $< -c -o $@
|
|
||||||
|
|
||||||
startup.o: ../startup.c
|
|
||||||
@$(CC) $(CFLAGS) $< -c -o $@
|
|
||||||
|
|
||||||
syscalls.o: ../syscalls.c
|
|
||||||
@$(CC) $(CFLAGS) $< -c -o $@
|
|
||||||
|
|
||||||
$(NAME).out: $(OBJECTS)
|
|
||||||
@$(CC) $(OBJECTS) $(LFLAGS) -o $(NAME).out
|
|
||||||
|
|
||||||
clean: # Redirecting both the stderr and stdout to /dev/null
|
|
||||||
@rm -f $(OBJECTS) > /dev/null 2>&1
|
|
||||||
@rm -f $(NAME).out > /dev/null 2>&1
|
|
||||||
@rm -f $(NAME).map > /dev/null 2>&1
|
|
136
project/main.c
136
project/main.c
|
@ -1,136 +0,0 @@
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "../common/rtos.h"
|
|
||||||
#include "../common/pwm.h"
|
|
||||||
#include "../common/bump.h"
|
|
||||||
#include "../common/reflectance.h"
|
|
||||||
#include "../common/motor.h"
|
|
||||||
#include "../common/delay.h"
|
|
||||||
|
|
||||||
#include "inc/msp432p401r.h"
|
|
||||||
|
|
||||||
// bit-banded addresses, positive logic
|
|
||||||
#define SW2IN ((*((volatile uint8_t *)(0x42098010)))^1)
|
|
||||||
#define SW1IN ((*((volatile uint8_t *)(0x42098004)))^1)
|
|
||||||
|
|
||||||
// bit-banded address
|
|
||||||
#define REDLED (*((volatile uint8_t *)(0x42098040)))
|
|
||||||
|
|
||||||
// bit-banded addresses
|
|
||||||
#define BLUEOUT (*((volatile uint8_t *)(0x42098068)))
|
|
||||||
#define GREENOUT (*((volatile uint8_t *)(0x42098064)))
|
|
||||||
#define REDOUT (*((volatile uint8_t *)(0x42098060)))
|
|
||||||
|
|
||||||
#define START_REFLECTANCE 9
|
|
||||||
|
|
||||||
int32_t bump_pressed; // semaphore
|
|
||||||
|
|
||||||
uint8_t bump_data, reflectance_data;
|
|
||||||
|
|
||||||
void WaitTouchRelease(void) {
|
|
||||||
while(!(SW1IN || SW2IN)); // wait for touch
|
|
||||||
while( SW1IN || SW2IN ); // wait for release
|
|
||||||
}
|
|
||||||
|
|
||||||
void SwitchInit(void) {
|
|
||||||
P1->SEL0 &= ~0x12;
|
|
||||||
P1->SEL1 &= ~0x12; // 1) configure P1.4 and P1.1 as GPIO
|
|
||||||
P1->DIR &= ~0x12; // 2) make P1.4 and P1.1 in
|
|
||||||
P1->REN |= 0x12; // 3) enable pull resistors on P1.4 and P1.1
|
|
||||||
P1->OUT |= 0x12; // P1.4 and P1.1 are pull-up
|
|
||||||
}
|
|
||||||
|
|
||||||
void RedLEDInit(void) {
|
|
||||||
P1->SEL0 &= ~0x01;
|
|
||||||
P1->SEL1 &= ~0x01; // 1) configure P1.0 as GPIO
|
|
||||||
P1->DIR |= 0x01; // 2) make P1.0 out
|
|
||||||
}
|
|
||||||
|
|
||||||
void ColorLEDInit(void) {
|
|
||||||
P2->SEL0 &= ~0x07;
|
|
||||||
P2->SEL1 &= ~0x07; // 1) configure P2.2-P2.0 as GPIO
|
|
||||||
P2->DIR |= 0x07; // 2) make P2.2-P2.0 out
|
|
||||||
P2->DS |= 0x07; // 3) activate increased drive strength
|
|
||||||
P2->OUT &= ~0x07; // all LEDs off
|
|
||||||
}
|
|
||||||
|
|
||||||
void led_task(void) {
|
|
||||||
while (true) {
|
|
||||||
if (SW1IN && SW2IN) {
|
|
||||||
GREENOUT = 1;
|
|
||||||
} else {
|
|
||||||
GREENOUT = 0;
|
|
||||||
}
|
|
||||||
if (SW1IN || SW2IN) {
|
|
||||||
REDLED = 1;
|
|
||||||
} else {
|
|
||||||
REDLED = 0;
|
|
||||||
}
|
|
||||||
if (SW1IN) {
|
|
||||||
BLUEOUT = 1;
|
|
||||||
} else {
|
|
||||||
BLUEOUT = 0;
|
|
||||||
}
|
|
||||||
if (SW2IN) {
|
|
||||||
REDOUT = 1;
|
|
||||||
} else {
|
|
||||||
REDOUT = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void drive_task(void) {
|
|
||||||
while (1) {
|
|
||||||
bump_pressed = 0;
|
|
||||||
MotorForward(1000, 1000);
|
|
||||||
Wait(&bump_pressed);
|
|
||||||
MotorBackward(800, 800);
|
|
||||||
Sleep(1000);
|
|
||||||
MotorLeft(800, 800);
|
|
||||||
Sleep(2000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t refl_tick_count = 0;
|
|
||||||
void reflectance_task(void) {
|
|
||||||
++refl_tick_count;
|
|
||||||
|
|
||||||
if (1 == (refl_tick_count % 10)) {
|
|
||||||
ReflectanceStart();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (2 == (refl_tick_count % 10)) {
|
|
||||||
reflectance_data = ReflectanceEnd();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void bump_task(void) {
|
|
||||||
bump_data = BumpRead();
|
|
||||||
if ((~bump_data & BUMP_PINS)) {
|
|
||||||
Signal(&bump_pressed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(void) {
|
|
||||||
BumpInit();
|
|
||||||
ReflectanceInit();
|
|
||||||
PWMInitMotor(3751);
|
|
||||||
MotorInit();
|
|
||||||
|
|
||||||
RedLEDInit();
|
|
||||||
ColorLEDInit();
|
|
||||||
SwitchInit();
|
|
||||||
RoundRobinInit();
|
|
||||||
AddThreads((void (*[])(void)){
|
|
||||||
led_task,
|
|
||||||
drive_task
|
|
||||||
});
|
|
||||||
AddPeriodicEventThreads((PeriodicEvent_t []) {
|
|
||||||
{reflectance_task, 1},
|
|
||||||
{bump_task, 100}
|
|
||||||
});
|
|
||||||
RoundRobinLaunch(48000); // 1ms
|
|
||||||
return 0; // never executes
|
|
||||||
}
|
|
Loading…
Reference in New Issue