Lab4: bootloader
来源:互联网 发布:陈田村拆车件淘宝店 编辑:程序博客网 时间:2024/04/30 10:55
写一个自己的简易bootloader,能通过串口执行两条最简单的指令:
l peek addr 以一个字为单位读取内存中addr 位置的数据(addr是4字节对齐,十六进制的 形式,长度为8位十六进制,例如 0x00008000),并以十六进制的形式输出
l poke addr data 以一个字为单位修改内存中 addr 位置的数据为 data(addr 是 4 字节对齐,十六进制的形式,长度为 8位十六进制, data 也是十六进制的形式,长度为8位十六进制)
实际连接图
定义全局变量:
#define BUFFSIZE 512#define BACKSPACE 127#define ENTER '\r'char str[100] = "Uart";struct uart { uint8_t *rear; uint8_t *front;};uint8_t aRxBuffer[BUFFSIZE]; struct uart uart_rev;
aRxBuffer数组用来接收缓冲区数组,结构uart用来接收缓冲区头尾指针。
输出重定义:
void SerialPutchar(char s){ HAL_UART_Transmit(&huart1, (uint8_t*)&s, 1, 500);}void SerialPuts(char* s){int i=0;while(s[i] != '\0'){SerialPutchar(s[i]);i++;}}
void ptrInc(uint8_t **ptr, uint8_t* base, int len){ *ptr += 1; if (*ptr >= base + len) *ptr = base;}
3)串口收发
串口接受采用中断接收至环形缓冲区的处理方式。生成工程后,uart_init()函数执行串口初始化,并设置中断优先级。
void uart_init(uint32_t BaudRate) { huart1.Instance = USART1; huart1.Init.BaudRate = 9600; huart1.Init.WordLength = UART_WORDLENGTH_8B; huart1.Init.StopBits = UART_STOPBITS_1; huart1.Init.Parity = UART_PARITY_NONE; huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart1.Init.Mode = UART_MODE_TX_RX; HAL_UART_Init(&huart1); __HAL_UART_ENABLE(&huart1); NVIC_SetPriority(USART1_IRQn, 0); NVIC_EnableIRQ(USART1_IRQn); uart_rev.front = aRxBuffer; uart_rev.rear = aRxBuffer; if (HAL_UART_Receive_IT(&huart1, (uint8_t*)aRxBuffer, 1) != HAL_OK){ HAL_UART_Transmit(&huart1, (uint8_t*)"error_h", 7, 500); }}
USART1_IRQHandler()调用HAL_UART_IRQHandler()函数,处理中断。
函数末尾调用HAL_UART_Receive_IT函数,设置串口数据的存储位置,该函数会设置存储位置和接受长度,当接收的数据达到指定长度时,会进入中断回调函数 HAL_UART_RxCpltCallback() 处理中断。
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle) { uint8_t ret = HAL_OK; char c = *uart_rev.rear; SerialPutchar(c); if (c == '\r'){ SerialPutchar('\n'); } ptrInc(&uart_rev.rear, aRxBuffer, BUFFSIZE); if (uart_rev.rear == uart_rev.front) ptrInc(&uart_rev.front, aRxBuffer, BUFFSIZE); do{ ret = HAL_UART_Receive_IT(UartHandle, uart_rev.rear, 1); }while(ret != HAL_OK);}void uart_init(uint32_t BaudRate) { huart1.Instance = USART1; huart1.Init.BaudRate = 9600; huart1.Init.WordLength = UART_WORDLENGTH_8B; huart1.Init.StopBits = UART_STOPBITS_1; huart1.Init.Parity = UART_PARITY_NONE; huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart1.Init.Mode = UART_MODE_TX_RX; HAL_UART_Init(&huart1); __HAL_UART_ENABLE(&huart1); NVIC_SetPriority(USART1_IRQn, 0); NVIC_EnableIRQ(USART1_IRQn); uart_rev.front = aRxBuffer; uart_rev.rear = aRxBuffer; if (HAL_UART_Receive_IT(&huart1, (uint8_t*)aRxBuffer, 1) != HAL_OK){ HAL_UART_Transmit(&huart1, (uint8_t*)"error_h", 7, 500); }}
串口信息读取到环形缓存区存放
int8_t uart_read(uint8_t *fmt, uint16_t time_out){ while(time_out){ if(uart_rev.front != uart_rev.rear){ *fmt=*uart_rev.front; ptrInc(&uart_rev.front, aRxBuffer, BUFFSIZE); return 0; } time_out--; } return (int8_t)-1; }int8_t uart_gets(uint8_t *fmt, uint16_t upperBound) { int count = 0; upperBound -= 1; while(count < upperBound){ if(uart_rev.front != uart_rev.rear){ char c = *uart_rev.front; ptrInc(&uart_rev.front, aRxBuffer, BUFFSIZE); if (c == ENTER){ break; } *fmt = c; if (c != BACKSPACE){ fmt++; count++; }else if(count > 0){ fmt--; count--; } } } *fmt = '\0'; return count; }
到这里,对于串口收发的函数封装完成,处理peek/poke指令。为了防止随便给poke指令的地址,崩坏程序,所以给了buff数组,并给出相应的地址及长度。
int buff[100]; buff[0] = sprintf(str, "Buffer Addr: %p Len: %d\r\n", buff, 100); HAL_UART_Transmit(&huart1, (uint8_t*)str, buff[0], 500); while (1) { int count = 0; char s[100]; char cmd[100]; SerialPuts("STM32 > "); count = uart_gets((uint8_t*)str, 100); sscanf(str, "%s", cmd); if (strcmp(cmd, "peek") == 0){ int addr = 0, args = 0; args = sscanf(str + 5, "%x %s", &addr, s);if(args == 1){sprintf(s, "PEEK: %x %x\r\n", addr, *((int*)addr));SerialPuts(s);}elseSerialPuts("Format Error\r\n"); }else if(strcmp(cmd, "poke") == 0){int addr = 0, args = 0, data=0; args = sscanf(str + 5, "%x %x %s", &addr, &data, s);if(args == 2){*((int*)addr) = data;sprintf(s, "POKE: %x %x\r\n", addr, *((int*)addr));SerialPuts(s);}elseSerialPuts("Format Error\r\n"); }else{ SerialPuts("Instruction Error\r\n"); } } }
测试结果:
0 0
- Lab4: bootloader
- 嵌入式lab4——Bootloader
- lab4
- lab4
- Lab4 Authentication
- JOS-lab4
- ucore lab4
- ucore lab4
- Bootloader
- BootLoader
- BootLoader
- BootLoader
- Bootloader
- bootLoader
- bootloader
- bootloader
- bootloader
- BootLoader
- Node.js
- readLine方法的简单练习,回答2016-04-27 的帖子的问题
- HDU 1542 Atlantis
- zabbix3.0 监控mysql服务器性能实现过程
- 课堂笔记之线程池
- Lab4: bootloader
- POJ_3074_Sudoku(DancingLinksX精确覆盖)
- htoi(十六进制转十进制)
- AFN
- Spark学习三:Spark Schedule以及idea的安装和导入源码
- Spark学习四:网站日志分析案例
- [Python]dict,set
- Java泛型
- google搜索引擎核心PageRank