Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Assingment/led switch #1

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions projects/lpc40xx_freertos/l3_drivers/gpio_lab.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/**
* @file gpio_lab.h
* @author Tejas Pidkalwar
* @date 11th Sept 2020
* @brief This file contains the prototypes of register bit manipulating
* functions for GPIO0 and GPIO1 as a part of LED_TASK assignment.
*/
#pragma once

#include <stdbool.h>
#include <stdint.h>

/**
* This struct is returned gpio__construct()
* All further APIs need instance of this struct to operate
*/
typedef struct {
uint8_t port_number : 3;
uint8_t pin_number : 5;
} gpio_lab_s;

// NOTE: The IOCON is not part of this driver

/**
* Alter the hardware registers to set the pin as input
* @param gpio GPIO structure of which base address we need
*/
void gpio_lab_set_as_input(gpio_lab_s gpio);

/**
* Alter the hardware registers to set the pin as output
* @param gpio GPIO structure of which base address we need
*/
void gpio_lab_set_as_output(gpio_lab_s gpio);

/**
* Alter the hardware registers to set the pin as high
* @param gpio GPIO structure of which base address we need
*/
void gpio_lab_set_high(gpio_lab_s gpio);

/**
* Alter the hardware registers to set the pin as low
* @param gpio GPIO structure of which base address we need
*/
void gpio_lab_set_low(gpio_lab_s gpio);

/**
* Alter the hardware registers to set the pin as low
* @param {uint8_t} pin_num => input the pin number want to access
* @param {bool} high - true => set pin high, false => set pin low
*/
void gpio_lab_set(gpio_lab_s gpio, bool high);

/**
* Should return the state of the pin (input or output, doesn't matter)
* @param {uint8_t} pin_num => input the pin number want to access
* @return {bool} level of pin high => true, low => false
*/
bool gpio_lab_get_level(gpio_lab_s gpio);
51 changes: 51 additions & 0 deletions projects/lpc40xx_freertos/l3_drivers/sources/gpio_lab.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/**
* @file gpio_lab.c
* @author Tejas Pidkalwar
* @date 11th Sept 2020
* @brief This file contains the implementations of register bit manipulating
* functions for GPIO0 and GPIO1 as a part of LED_TASK assignment.
*/

#include "gpio_lab.h"

#include "lpc40xx.h"

/**
* array of pointer ro GPIO ports' base addresses
*/
static LPC_GPIO_TypeDef *gpio_lab_port_memory_map[] = {LPC_GPIO0, LPC_GPIO1, LPC_GPIO2,
LPC_GPIO3, LPC_GPIO4, LPC_GPIO5};

/**
* Retruns the pointer to an base address of an given port
* @param gpio GPIO structure of which base address we need
* @return (LPC_GPIO_TypeDef *) pointer to the base address of given port
*/
static LPC_GPIO_TypeDef *gpio_lab_get_struct(gpio_lab_s gpio) {
return (LPC_GPIO_TypeDef *)gpio_lab_port_memory_map[gpio.port_number];
}

/**
* Retruns the pin masked value for the given GPIO
* @param gpio GPIO structure of which base address we need
* @return pin masked value for the given GPIO
*/
static uint32_t gpio_lab_get_pin_mask(gpio_lab_s gpio) { return (1 << gpio.pin_number); }

void gpio_lab_set_as_input(gpio_lab_s gpio) { gpio_lab_get_struct(gpio)->DIR &= ~gpio_lab_get_pin_mask(gpio); }

void gpio_lab_set_as_output(gpio_lab_s gpio) { gpio_lab_get_struct(gpio)->DIR |= gpio_lab_get_pin_mask(gpio); }

void gpio_lab_set_high(gpio_lab_s gpio) { gpio_lab_get_struct(gpio)->SET = gpio_lab_get_pin_mask(gpio); }

void gpio_lab_set_low(gpio_lab_s gpio) { gpio_lab_get_struct(gpio)->CLR = gpio_lab_get_pin_mask(gpio); }

void gpio_lab_set(gpio_lab_s gpio, bool high) {
// based on the high bit's input value manipulate GPIO PIN.
if (high)
gpio_lab_get_struct(gpio)->SET = gpio_lab_get_pin_mask(gpio);
else
gpio_lab_get_struct(gpio)->CLR = gpio_lab_get_pin_mask(gpio);
}

bool gpio_lab_get_level(gpio_lab_s gpio) { return (gpio_lab_get_struct(gpio)->PIN & gpio_lab_get_pin_mask(gpio)); }
122 changes: 119 additions & 3 deletions projects/lpc40xx_freertos/l5_application/main.c
Original file line number Diff line number Diff line change
@@ -1,22 +1,138 @@
#include <stdio.h>

#include "FreeRTOS.h"
#include "queue.h"
#include "semphr.h"
#include "task.h"

#include "board_io.h"
#include "common_macros.h"
#include "gpio.h"
#include "gpio_lab.h"
#include "periodic_scheduler.h"
#include "sj2_cli.h"

/**
* Local Macros
*/
#define INVALID_SWITCH 4
#define MAX_LEDS 4

/**
* Local Functions
*/
static void create_blinky_tasks(void);
static void create_uart_task(void);
static void blink_task(void *params);
static void uart_task(void *params);

/**
* Local Variables
*/
static SemaphoreHandle_t switch_press_indication;
static volatile uint8_t led_index = 0;

static void led_task(void *task_parameter) {
// Available LEDs served under this task
const gpio_lab_s led[] = {{1, 18}, {1, 24}, {1, 26}, {2, 3}};
while (true) {
// Check every 1000ms whether semaphore is available. Other time FreeRTOS make this task sleep
if (xSemaphoreTake(switch_press_indication, 1000)) {
// Temperory variable to track remaining LEDs to be blinked
int temp = MAX_LEDS;

// This loop will turn on all LEDs starting led_index
while (temp) {
printf("led on index =%d \n", led_index);
gpio_lab_set_high(led[led_index++ % 4]);
vTaskDelay(100);
temp--;
}
temp = MAX_LEDS;

// This loop will turn off all LEDs starting led_index
while (temp) {
printf("led off index =%d \n", led_index);
gpio_lab_set_low(led[led_index++ % 4]);
vTaskDelay(100);
temp--;
}
} else {
puts("Timeout: No switch press indication for 1000ms");
}
}
}

static void switch_task(void *task_parameter) {
// Available switches served under this task
const gpio_lab_s switch_index[] = {{1, 19}, {1, 15}, {0, 30}, {0, 29}};
// Initialize the switch to be toggle to invalid switch
uint8_t toggle_switch = INVALID_SWITCH;

while (true) {
// Monitor pressed switch for successful toggle
switch (toggle_switch) {
case 3:
if (!gpio_lab_get_level(switch_index[3])) {
toggle_switch = INVALID_SWITCH;
led_index = 0;
// Release the semaphore when the switch is successfully toggled
if (!xSemaphoreGive(switch_press_indication))
puts("Unable to release the semaphore");
}
break;
case 2:
if (!gpio_lab_get_level(switch_index[2])) {
toggle_switch = INVALID_SWITCH;
led_index = 1;
// Release the semaphore when the switch is successfully toggled
if (!xSemaphoreGive(switch_press_indication))
puts("Unable to release the semaphore");
}
break;
case 1:
if (!gpio_lab_get_level(switch_index[1])) {
toggle_switch = INVALID_SWITCH;
led_index = 2;
// Release the semaphore when the switch is successfully toggled
if (!xSemaphoreGive(switch_press_indication))
puts("Unable to release the semaphore");
}
break;
case 0:
if (!gpio_lab_get_level(switch_index[0])) {
toggle_switch = INVALID_SWITCH;
led_index = 3;
// Release the semaphore when the switch is successfully toggled
if (!xSemaphoreGive(switch_press_indication))
puts("Unable to release the semaphore");
}
break;
default:
break;
}

// Monitor the pressed switch
if (gpio_lab_get_level(switch_index[3]))
toggle_switch = 3;
else if (gpio_lab_get_level(switch_index[2]))
toggle_switch = 2;
else if (gpio_lab_get_level(switch_index[1]))
toggle_switch = 1;
else if (gpio_lab_get_level(switch_index[0]))
toggle_switch = 0;
// Task should always sleep otherwise they will use 100% CPU
// This task sleep also helps avoid spurious semaphore give during switch debeounce
vTaskDelay(100);
}
}

int main(void) {
create_blinky_tasks();
create_uart_task();

switch_press_indication = xSemaphoreCreateBinary();

xTaskCreate(led_task, "led", 2048 / sizeof(void *), NULL, PRIORITY_LOW, NULL);
xTaskCreate(switch_task, "switch", 2048 / sizeof(void *), NULL, PRIORITY_LOW, NULL);

puts("Starting RTOS");
vTaskStartScheduler(); // This function never returns unless RTOS scheduler runs out of memory and fails
Expand Down Expand Up @@ -97,4 +213,4 @@ static void uart_task(void *params) {
printf("This is a more efficient printf ... finished in");
printf(" %lu ticks\n\n", (xTaskGetTickCount() - ticks));
}
}
}