-
Notifications
You must be signed in to change notification settings - Fork 4
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
Added simulation project #256
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<!-- | ||
General guidelines | ||
These are just guidelines, not strict rules - document however seems best. | ||
A README for a firmware-only project (e.g. Babydriver, MPXE, bootloader, CAN explorer) should answer the following questions: | ||
- What is it? | ||
- What problem does it solve? | ||
- How do I use it? (with usage examples / example commands, etc) | ||
- How does it work? (architectural overview) | ||
A README for a board project (powering a hardware board, e.g. power distribution, centre console, charger, BMS carrier) should answer the following questions: | ||
- What is the purpose of the board? | ||
- What are all the things that the firmware needs to do? | ||
- How does it fit into the overall system? | ||
- How does it work? (architectural overview, e.g. what each module's purpose is or how data flows through the firmware) | ||
--> | ||
# simulation | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"libs": [ | ||
"FreeRTOS", | ||
"ms-common" | ||
] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
#pragma once | ||
|
||
#include <arpa/inet.h> | ||
#include <errno.h> | ||
#include <fcntl.h> | ||
#include <net/if.h> | ||
#include <poll.h> | ||
#include <pthread.h> | ||
#include <semaphore.h> | ||
#include <stdio.h> | ||
#include <string.h> | ||
#include <sys/ioctl.h> | ||
#include <sys/socket.h> | ||
#include <sys/types.h> | ||
#include <unistd.h> | ||
|
||
#include "adc.h" | ||
#include "gpio.h" | ||
#include "gpio_it.h" | ||
#include "i2c.h" | ||
#include "log.h" | ||
|
||
#define x86 1 | ||
#define PORT 2520 | ||
|
||
void sim_init(int sock_num); | ||
|
||
typedef enum { | ||
GPIO_SET = 0, | ||
GPIO_TOGGLE, | ||
GPIO_IT_TRIGGER, | ||
ADC_SET_READING, | ||
I2C_SET_READING, | ||
SPI_SET_RX, | ||
UART, | ||
NUM_OF_OPERATIONS | ||
} Operations; | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,206 @@ | ||
#include "operation_listener.h" | ||
#include "spi.h" | ||
|
||
bool s_keep_alive = true; | ||
|
||
void gpio_set_sim(char buffer[]) { | ||
int param1, param2, param3; | ||
LOG_DEBUG("GPIO_SET\n"); | ||
if (length != 3) { | ||
LOG_DEBUG("Invalid length: %d\n", length); | ||
return; | ||
} | ||
|
||
sscanf(buffer, "%d, %d, %d", ¶m1, ¶m2, ¶m3); | ||
if (param1 < 0 || param2 < 0 || param3 < 0 || param1 > 6 || param2 > 16 || param3 > 1) { | ||
LOG_DEBUG("Invalid param, 1: %d, 2: %d, 3: %d\n", param1, param2, param3); | ||
return; | ||
} | ||
|
||
GpioAddress GPIO_SET_ADDR = { .port = param1, .pin = param2 }; | ||
gpio_set_state(&GPIO_SET_ADDR, param3); | ||
} | ||
|
||
void gpio_toggle_sim(int length, char buffer[]) { | ||
int param1, param2; | ||
LOG_DEBUG("GPIO_TOGGLE\n"); | ||
if (length != 2) { | ||
LOG_DEBUG("Invalid length: %d\n", length); | ||
return; | ||
} | ||
sscanf(buffer, "%d, %d, %d", ¶m1, ¶m2); | ||
if (param1 < 0 || param2 < 0 || param1 > 6 || param2 > 16) { | ||
LOG_DEBUG("Invalid param, 1: %d, 2: %d\n", param1, param2); | ||
return; | ||
} | ||
|
||
GpioAddress GPIO_TOGGLE_ADDR = { .port = param1, .pin = param2 }; | ||
gpio_toggle_state(&GPIO_TOGGLE_ADDR); | ||
} | ||
|
||
void gpio_it_trigger_sim(int length, char buffer[]) { | ||
LOG_DEBUG("GPIO_IT_TRIGGER\n"); | ||
int param1, param2; | ||
if (length != 2) { | ||
LOG_DEBUG("Invalid length: %d\n", length); | ||
return; | ||
} | ||
sscanf(buffer, "%d, %d", ¶m1, ¶m2); | ||
if (param1 < 0 || param2 < 0 || param1 > 6 || param2 > 16) { | ||
LOG_DEBUG("Invalid param, 1: %d, 2: %d\n", param1, param2); | ||
return; | ||
} | ||
|
||
GpioAddress IT_TRIGGER_ADDR = { .port = param1, .pin = param2 }; | ||
gpio_it_trigger_interrupt(&IT_TRIGGER_ADDR); | ||
} | ||
|
||
void adc_set_reading_sim(int length, char buffer[]) { | ||
LOG_DEBUG("ADC_SET_READING\n"); | ||
int param1, param2, param3; | ||
if (length != 3) { | ||
LOG_DEBUG("Invalid length: %d\n", length); | ||
return; | ||
} | ||
|
||
sscanf(buffer, "%d, %d, %d", ¶m1, ¶m2, ¶m3); | ||
if (param1 < 0 || param2 < 0 || param3 < 0 || param1 > 6 || param2 > 16) { | ||
LOG_DEBUG("Invalid param, 1: %d, 2: %d, 3: %d\n", param1, param2, param3); | ||
return; | ||
} | ||
|
||
GpioAddress ADC_SET_READING_ADDR = { .port = param1, .pin = param2 }; | ||
adc_set_reading(ADC_SET_READING_ADDR, param3); | ||
} | ||
|
||
void i2c_set_reading_sim(int length, char buffer[]) { | ||
int param1, param2; | ||
LOG_DEBUG("I2C_SET_READING\n"); | ||
if (length != 3) { | ||
LOG_DEBUG("Invalid length: %d\n", length); | ||
return; | ||
} | ||
|
||
sscanf(buffer, "%d, %d, %[^\n\t]", ¶m1, ¶m2, buffer); | ||
if (param1 < 0 || param2 < 0 || param1 > 1) { | ||
LOG_DEBUG("Invalid param, param1: %d, param2: %d\n", param1, param2); | ||
return; | ||
} | ||
|
||
I2CPort i2c_port = param1; | ||
i2c_set_data(i2c_port, (uint8_t *)&buffer, (size_t)param2); | ||
} | ||
|
||
void spi_set_rx_sim(int length, char buffer[]) { | ||
LOG_DEBUG("SPI_SET_RX\n"); | ||
int param1; | ||
if (length != 2) { | ||
LOG_DEBUG("Invalid length: %d\n", length); | ||
return; | ||
} | ||
|
||
sscanf(buffer, "%d, %[^\n\t]", ¶m1, buffer); | ||
if (param1 < 0) { | ||
LOG_DEBUG("Invalid param, param1: %d", param1); | ||
return; | ||
} | ||
|
||
spi_set_rx((uint8_t *)&buffer, param1); | ||
} | ||
|
||
void sim_init(int sock_num) { | ||
char buffer[2024]; | ||
LOG_DEBUG("Simulation thread started\n"); | ||
int res; | ||
int operation, length; | ||
char rcv[1]; | ||
int p; | ||
Operations input; | ||
|
||
while (s_keep_alive) { | ||
res = 0; | ||
memset(buffer, 0, sizeof(buffer)); | ||
p = 0; | ||
LOG_DEBUG("Listening\n"); | ||
while (s_keep_alive) { | ||
memset(rcv, 0, sizeof(rcv)); | ||
res = recv(sock_num, rcv, 1, 0); | ||
if (res == 1) { | ||
if (rcv[0] != '\n') { | ||
buffer[p] = rcv[0]; | ||
p++; | ||
} else { | ||
break; | ||
} | ||
} | ||
} | ||
LOG_DEBUG("Message received!\n"); | ||
sscanf(buffer, "%d: %d, %[^\n\t]", &operation, &length, buffer); | ||
if (operation < 0 || operation > 6) { | ||
LOG_DEBUG("Invalid operation: %d\n", operation); | ||
continue; | ||
} | ||
|
||
input = operation; | ||
switch (input) { | ||
case GPIO_SET: | ||
gpio_set_sim(length, buffer) break; | ||
case GPIO_TOGGLE: | ||
gpio_toggle_sim(length, buffer); | ||
break; | ||
case GPIO_IT_TRIGGER: | ||
gpio_it_trigger_sim(length, buffer); | ||
break; | ||
case ADC_SET_READING: | ||
adc_set_reading_sim(length, buffer); | ||
break; | ||
case I2C_SET_READING: | ||
i2c_set_reading_sim(length, buffer); | ||
break; | ||
case SPI_SET_RX: | ||
spi_set_rx_sim(length, buffer); | ||
break; | ||
case UART: | ||
LOG_DEBUG("UART\n"); | ||
break; | ||
default: | ||
LOG_DEBUG("UNRECOGNIZED OPERATION: %d\n", input); | ||
} | ||
usleep(1000000); | ||
} | ||
} | ||
|
||
int main(int argc, char *argv[]) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You should be getting the port from the args, but this is fine for now |
||
LOG_DEBUG("Operation listener thread started\n"); | ||
int socketfd = socket(AF_INET, SOCK_STREAM, 0); | ||
if (socketfd < 0) { | ||
LOG_DEBUG("Socket error: %d", socketfd); | ||
return 0; | ||
} | ||
LOG_DEBUG("Socket successful\n"); | ||
struct sockaddr_in server_addr; | ||
server_addr.sin_family = AF_INET; | ||
server_addr.sin_port = htons(2520); | ||
server_addr.sin_addr.s_addr = htonl(INADDR_ANY); | ||
int status = bind(socketfd, (struct sockaddr *)&server_addr, sizeof(server_addr)); | ||
if (status < 0) { | ||
LOG_DEBUG("Bind failed: %d\n", status); | ||
return 0; | ||
} | ||
LOG_DEBUG("Bind successful\n"); | ||
if (listen(socketfd, 5) < 0) { | ||
LOG_DEBUG("Listen failed\n"); | ||
return 0; | ||
} | ||
LOG_DEBUG("Listen successful\n"); | ||
int newsockfd = accept(socketfd, NULL, NULL); | ||
if (newsockfd < 0) { | ||
LOG_DEBUG("Accept failed: %d \n", newsockfd); | ||
return 0; | ||
} | ||
LOG_DEBUG("Accept successful\n"); | ||
|
||
sim_init(newsockfd); | ||
close(newsockfd); | ||
close(socketfd); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
#include <arpa/inet.h> | ||
#include <errno.h> | ||
#include <fcntl.h> | ||
#include <net/if.h> | ||
#include <poll.h> | ||
#include <pthread.h> | ||
#include <semaphore.h> | ||
#include <stdio.h> | ||
#include <string.h> | ||
#include <sys/ioctl.h> | ||
#include <sys/socket.h> | ||
#include <sys/types.h> | ||
#include <unistd.h> | ||
|
||
#include "gpio.h" | ||
#include "gpio_it.h" | ||
#include "log.h" | ||
|
||
#define PORT 2520 | ||
|
||
int main() { | ||
int socketfd; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also consider putting this socket logic into a function so other users don't need to copy this |
||
struct sockaddr_in server_addr; | ||
socketfd = socket(AF_INET, SOCK_STREAM, 0); | ||
if (socketfd < 0) { | ||
LOG_DEBUG("Socket error: %d \n", socketfd); | ||
return 0; | ||
} | ||
LOG_DEBUG("Socket successful\n"); | ||
|
||
server_addr.sin_family = AF_INET; | ||
server_addr.sin_port = htons(PORT); | ||
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); | ||
|
||
if (connect(socketfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { | ||
LOG_DEBUG("Connect error\n"); | ||
return 0; | ||
} | ||
LOG_DEBUG("Connect successful\n"); | ||
const char *test1 = "0: 3, 2, 16, 0\n"; | ||
const char *test2 = "1: 2, 2, 16\n"; | ||
const char *test3 = "2: 2, 2, 16\n"; | ||
const char *test4 = "3: 3, 2, 16, 3\n"; | ||
const char *test5 = "4: 3, 1, 5, hello\n"; | ||
const char *test6 = "5: 3, 1, 5, hello\n"; | ||
const char *test7 = "6: 3, 2, 5, hello\n"; | ||
const char *test8 = "7: 3, 2, 16, 0"; | ||
send(socketfd, test1, strlen(test1), 0); | ||
send(socketfd, test2, strlen(test2), 0); | ||
send(socketfd, test3, strlen(test3), 0); | ||
send(socketfd, test4, strlen(test4), 0); | ||
send(socketfd, test5, strlen(test5), 0); | ||
send(socketfd, test6, strlen(test6), 0); | ||
send(socketfd, test7, strlen(test7), 0); | ||
send(socketfd, test8, strlen(test8), 0); | ||
close(socketfd); | ||
return 0; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe just add a
NUM_OF_OPERATIONS
at the end