spinmry's Lab

绝赞摸鱼中Orz

Category

  • Algorithm
  • Hardware
  • Homelab
  • Programming
  • Retro
  • Software

Tags

  • 算法
  • OI
  • Linux
  • 数据结构
  • HardwareHacking
  • RobotC
  • 图论
  • 离散化
  • Kruskal
  • 计算设备
  • Homelab
  • 机器人
  • QQBot
  • 平衡树
  • 线段树
  • VEX
  • Nspire
  • 数论
  • ACG
  • Python
  • iLO
  • 树状数组
  • ARM
  • Tarjan
  • Loongson
  • Mattermost
  • Wolfram
  • 网页
  • Vintage
  • 单片机
  • 动态规划
  • 爬虫
  • 分块
  • STM32

Recent replies

  • rantrism 发表于「解决 Linux Optimus 混合模式下独立显卡外接显示器卡顿的问题」
  • 千羽 发表于「在 Loongson 2F 上编译 Common Desktop Environment」
  • spinmry 发表于「QQ - Mattermost 双向转发机器人」
  • ilghar_kus 发表于「QQ - Mattermost 双向转发机器人」
  • polarnova 发表于「被历史遗忘的Linux PDA——Sharp Zaurus SL-5600评测 」

友情链接

空白酱
Woshiluo
FlyGoat
BeyondLimits
Memo von EFS
Paizhang
Ntzyz
ZephRay
Polarnova
Tautcany
NekoDaemon
MaxAlex
Abyss Studio
EE Archeology 电子考古学
桜庭清夏的小站
欠陥電気の摸鱼小池
白玉楼製作所

娱乐向跑分

Coremark
Linpack
分类:Hardware

优雅地使用计算器上网!(下) 定制你的 Linux for Nspire

2020 年 1 月 26 日分类:Hardware#HardwareHacking#计算设备#Nspire#Linux

优雅地使用计算器上网!(下) 定制你的 Linux for Nspire

(距离上篇教程发布已经整整一个学期过去了,终于有时间填这个坑了)
注意:本篇教程是面向小白向的,但是仍建议有一定 Linux 基础的计算器玩家尝试 本篇教程将教你如何从零开始定制 Nspire 能使用的 Linux 系统,包括制作 rootfs,配置并编译内核与各类驱动模块


0x00 准备工作

需要准备的东西:
一份 Linux Kernel 源码,可以在 https://kernel.org/ 下载
(需要注意的是,Linux 内核在 4.14 以后的版本中对 Nspire 的支持有些许问题,故建议下载 4.14 以及之前的 longterm 版本)
一台 Linux 系统的点好,并需要配置好交叉编译工具链
一个 4G 以上容量的 U 盘

0x01 制作 rootfs

关于 rootfs 是什么,你可以自行查阅 Wikipedia (逃) 首先你需要安装 debootstrap 等工具,以 Manjaro 系统为例:
sudo pacman -S binfmt-support qemu-user-static debootstrap
其中,debootstrap 是用来制作 rootfs 的工具,而 qemu-user-static 则允许你 chroot 到不同体系结构的 rootfs 中

安装完成后,挂载准备好的 U 盘到任意位置,执行
sudo debootstrap --arch=armel --foreign buster /*挂载 U 盘的位置*/ https://mirrors.ustc.edu.cn/debian
其中,
buster 代表你制作的 rootfs 系统的版本(Debian 10)
armel 全称是 arm eabi little endian,代表你制作的 rootfs 软件包的体系结构,因为 Nspire 使用的是一颗 arm926ejs 内核的处理器,故选择此版本

MORE

优雅地使用计算器上网!(上) Nspire CX 运行教程 & 效果展示

2019 年 8 月 5 日分类:Hardware#HardwareHacking#Linux#计算设备#Nspire

优雅地使用计算器上网!(上) Nspire CX 运行教程 & 效果展示

RT,在刚接触 Nspire 上运行 Linux 的时候就在想,是否可以在计算器上移植一个网卡驱动来实现计算器上网?外国论坛和油管上也有计算器上网的视频。然而无论是 cncalc 还是其他国内的计算器社区都对此很少有研究。在自己尝试过 Hackspire 上的 Linux 教程以后,发现它的内核已经很久没有更新过,且 rootfs 完全无法正常启动。正好这两天暑假抽出了时间,准备开始从零开始自己搭建一个计算器 Linux 内核并且做出一个比较完整的运行环境。经过三个晚上的努力,终于跑起来了 Linux 4.4.185 + Debian 10 + MT7601U 无线网卡驱动,成功实现计算器上网!(在此感谢在编译内核中给我很大帮助的dalao @FlyGoat)

在上半篇文章中,我打算主要展示运行效果以及怎样在 Nspire 计算器上运行已经制作好的内核和 rootfs,于是具体内核的编译细节,网卡驱动移植以及 rootfs 制作将放到下半篇文章中。

( ps : 本人刚刚接触嵌入式 Linux,如有词语使用不当还请轻喷 Orz )

MORE

Kindle 折腾笔记

2019 年 6 月 11 日分类:Hardware#HardwareHacking

Kindle 折腾笔记

久违的更一片博客
RT,前几天重新买了一块泡面盖(划掉)Kindle Paperwhite 3。下面是上手以后的例行折腾。
开机,系统版本 5.9.2 ,下载书伴上的 5.9.6.1 版本特质固件下载地址并更新,更新完毕后登录自己的 Amazon 帐号,并在根目录建立 update.bin.tmp.partial 文件夹,防止其连接网络后自动更新。
第二步,下载 kindle-jb-factory 并在系统搜索栏键入 ;installHtml 完成越狱。
第三步,安装 hotfix 保证升级固件后保持越狱。

MORE

基于STM32的环境监测器

2019 年 2 月 17 日分类:Hardware#STM32#单片机

基于STM32的环境监测器

0x00 背景&功能描述

研究性学习课题要用到这玩意…于是尝试用stm32捏了一个… 第一次玩stm32,为了方便就直接拿STM32CubeMX生成了这个工程… 芯片为STM32F407GZT6,使用了外部RTC,具体时钟树设置参考CubeMX工程文件。 功能嘛,每隔一段时间获取实时PM2.5,PM10,CO2浓度与环境温湿度,并将其存储入SD卡(FAT32分区)中。同时也会向USART1中打印日志。 USART1-3波特率均为9600,

0x01 硬件部分

温湿度传感器(DHT22/AM2303) -> PA1 *USART1(PA9 PA10) PM2.5(G7 PMS7003) -> USART2(PA3 PA4) CO2(DS-CO2-20) -> USART3(PE14 PE15)

0x02 代码

项目由CubeMX自动生成,以下仅展示部分代码 GitHub项目地址 ps:请忽视逼死强迫症的缩进…就让Keil uvision那个辣鸡的IDE背锅吧

RTC_DateTypeDef sDate;
RTC_TimeTypeDef sTime;
uint8_t second_tmp = 0;

void LED0_off(){HAL_GPIO_WritePin(LED0_GPIO_Port, LED0_Pin, GPIO_PIN_SET);}
void LED1_off(){HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET);}

void LED0_on(){HAL_GPIO_WritePin(LED0_GPIO_Port, LED0_Pin, GPIO_PIN_RESET);}
void LED1_on(){HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET);}

uint8_t PMSensorBuffer[128];
uint8_t PMSensor[17];
int TOT = 0, PMSensorLen;

//PM Sensor

struct PMSensor{
	int PM1_0_CF, PM2_5_CF, PM10_CF, PM1_0, PM2_5, PM10;
}PMResult;

void ListenPMSensor(){
	memset(PMSensorBuffer, 0, sizeof(PMSensorBuffer));
	memset(PMSensor, 0, sizeof(PMSensor));
	
	HAL_UART_Receive(&huart2, (uint8_t*)PMSensorBuffer, 128, 3200);
	HAL_Delay(800);
	
	//printf("", PMSensorBuffer);
	for(int i = 0; i <= 127; ++i){
		//printf("%c \n", PMSensorBuffer[i]);
		if(PMSensorBuffer[i] == 'B' && PMSensorBuffer[i+1] == 'M'){			
			for(PMSensorLen = 0; PMSensorLen <= 31; ++PMSensorLen){
				PMSensor[PMSensorLen] = PMSensorBuffer[i + PMSensorLen];
			}
			break;
		}
	}
	
	HAL_Delay(2000);
	return ;
}

void GetPMSensor(void){
	uint16_t Buffer_Len;
	Buffer_Len = (uint16_t)((PMSensor[2] << 8) | PMSensor[3]);
	if(Buffer_Len == 28) {
		
		PMResult.PM1_0_CF = (uint16_t)((PMSensor[4]<<8) | PMSensor[5]);
		PMResult.PM2_5_CF = (uint16_t)((PMSensor[6]<<8) | PMSensor[7]);
		PMResult.PM10_CF 	= (uint16_t)((PMSensor[8]<<8) | PMSensor[9]);
		PMResult.PM1_0 	= (uint16_t)((PMSensor[10]<<8) | PMSensor[11]);
		PMResult.PM2_5 	= (uint16_t)((PMSensor[12]<<8) | PMSensor[13]);
		PMResult.PM10 	= (uint16_t)((PMSensor[14]<<8) | PMSensor[15]);		
		
	}
	else if(Buffer_Len == 20){
		
		PMResult.PM1_0_CF = (uint16_t)((PMSensor[4]<<8) | PMSensor[5]);
		PMResult.PM2_5_CF = (uint16_t)((PMSensor[6]<<8) | PMSensor[7]);
		PMResult.PM10_CF 	= (uint16_t)((PMSensor[8]<<8) | PMSensor[9]);
		PMResult.PM1_0 	= (uint16_t)((PMSensor[10]<<8) | PMSensor[11]);
		PMResult.PM2_5 	= (uint16_t)((PMSensor[12]<<8) | PMSensor[13]);
		PMResult.PM10 	= (uint16_t)((PMSensor[14]<<8) | PMSensor[15]);
		
	}
}

int CheckPMSensor(){
	
	uint16_t 	Cal_CheckSum;
	uint16_t 	Buffer_CheckSum;
	uint16_t 	Buffer_Len;
	uint8_t 	i;
	
	int Result = 0;

	if((PMSensor[0] == 'B')&&(PMSensor[1] == 'M')){
		Buffer_Len = (uint16_t)((PMSensor[2] << 8) | PMSensor[3]);

		Buffer_CheckSum = (uint16_t)((PMSensor[Buffer_Len + 2] << 8) | PMSensor[Buffer_Len + 3]);

		Cal_CheckSum = 0;
		for(i=0;i<(Buffer_Len + 2);i++){
			Cal_CheckSum += PMSensor[i];
		}

		if(Cal_CheckSum == Buffer_CheckSum)
			Result = 1;
	}
	return Result;
}


//CO2 sensor
uint8_t CO2SensorBuffer[12];
uint8_t CO2Sensor[12];

int CO2SensorLen = 0, CO2SensorResult = 0;

void ListenCO2Sensor(){
	memset(CO2SensorBuffer, 0, sizeof(CO2SensorBuffer));
	memset(CO2Sensor, 0, sizeof(CO2Sensor));
	
	uint8_t CO2Transmit[12] = {0x42, 0x4D, 0xE3, 0x00, 0x00, 0x01, 0x72};
	
	HAL_UART_Transmit(&huart3, CO2Transmit, 7, 0xFFFF);
	HAL_UART_Receive(&huart3, (uint8_t*)CO2SensorBuffer, 12, 800);
	HAL_Delay(800);
	
	for(int i = 0; i <= 11; ++i){
		//printf("%c", CO2SensorBuffer[i]);
		if(CO2SensorBuffer[i] == 'B' && CO2SensorBuffer[i+1] == 'M'){
			for(CO2SensorLen = 0; CO2SensorLen <= 11; ++CO2SensorLen){	
				CO2Sensor[CO2SensorLen] = CO2SensorBuffer[i + CO2SensorLen];
			}
			break;
		}
		HAL_Delay(500);
	}
	HAL_Delay(2000);
	return ;
}


int CheckCO2Sensor(){
	
	uint16_t 	Cal_CheckSum;
	uint16_t 	Buffer_CheckSum;
	uint16_t 	Buffer_Len;
	uint8_t 	i;
	
	int Result = 0;

	if((CO2Sensor[0] == 'B')&&(CO2Sensor[1] == 'M')){
		
		Buffer_Len = (uint16_t)((CO2Sensor[2] << 8) | CO2Sensor[3]);
		//printf("LEN:%d \n",Buffer_Len);
		Buffer_CheckSum = (uint16_t)((CO2Sensor[Buffer_Len + 2] << 8) | CO2Sensor[Buffer_Len + 3]);
        
		Cal_CheckSum = 0;
		for(i=0;i<(Buffer_Len + 2);i++){
			Cal_CheckSum += CO2Sensor[i];
		}
		//printf("CALSUM:%d, BUFFSUM:%d \n", Cal_CheckSum, Buffer_CheckSum);
		if(Cal_CheckSum == Buffer_CheckSum)
			Result = 1;
	}
	return Result;
}

void GetCO2Sensor(){
	CO2SensorResult = (uint16_t)((CO2Sensor[4]<<8) | CO2Sensor[5]);
	return ;
}

FATFS SDFatFs;
FIL MyFile;

void WriteFile(){
	
	LED0_off();
	LED1_off();
	
	uint32_t byteswritten;
	char nowdate[21];
	sprintf(nowdate, "[20%02d-%02d-%02d %02d:%02d:%02d]\n",
				sDate.Year,
				sDate.Month,
				sDate.Date,
				sTime.Hours,
				sTime.Minutes,
				sTime.Seconds
	);
	char wtext[150] = " ";
	sprintf(wtext, "%sCO2 : _%04d_ ppm\nPM2.5 : _%04d_ ug/m3\nPM10 : _%04d_ ug/m3\n", 
		nowdate,
		CO2SensorResult, 
		PMResult.PM2_5, 
		PMResult.PM10
	);
	char FileName[25] = " ";
	sprintf(FileName, "Sensor_%02d%02d%02d%02d%02d_.txt", 
		sDate.Year,
		sDate.Month,
		sDate.Date,
		sTime.Hours,
		sTime.Minutes
	);
	printf("%s\nFileName:%s\n", wtext, FileName);
	if(f_mount(&SDFatFs, (TCHAR const*)SDPath, 0) == FR_OK){
		PrintTime();
		printf("[SD_FATFS_STAT] Mount Successful!\n");
		if(f_open(&MyFile, (TCHAR const*)FileName, FA_CREATE_ALWAYS | FA_WRITE) == FR_OK){
			PrintTime();
			printf("[SD_FATFS_STAT] Open File Successful!\n");
			FRESULT res = f_write(&MyFile, wtext, (unsigned int)strlen(wtext), (void *)&byteswritten);
			if((byteswritten == 0) || (res != FR_OK)){
				PrintTime();
				printf("[SD_FATFS_STAT] Write Failed!\n");
			}
			else{
				f_close(&MyFile);
				PrintTime();
				printf("[SD_FATFS_STAT] Write Successful!\n");
			}
		}
		else{
				PrintTime();
				printf("[SD_FATFS_STAT] Open File Failed!\n");
		}
	}else{
		PrintTime();
		printf("[SD_FATFS_STAT] Mount Failed!\n");
	}
	
}

void PrintTime(){
	
	printf("[20%02d-%02d-%02d %02d:%02d:%02d]",
				sDate.Year,
				sDate.Month,
				sDate.Date,
				sTime.Hours,
				sTime.Minutes,
				sTime.Seconds
	);
	return ;
}

void CheckState(){
	
	LED0_on();
	LED1_off();
	
	ListenCO2Sensor();
	if(CheckCO2Sensor()){
		PrintTime();
		printf("[CO2_SENSOR_STATE] Success!\n");
		GetCO2Sensor();
	}
	
	else{
		PrintTime();
		printf("[CO2_SENSOR_STATE] Error!\n");
	}
	
	/*PM SENSOR READ*/
	HAL_Delay(100);
	LED0_on();
	LED0_off();
	ListenPMSensor();
	if(CheckPMSensor()){
		PrintTime();
		printf("[PM_SENSOR_STATE] Success!\n");
		GetPMSensor();
	}
	else{
		PrintTime();
		printf("[PM_SENSOR_STATE] Error!\n");
	}
	
	PrintTime();
	printf("\nCO2: %d ppm \nPM2.5: %d ug/m^3\nPM10: %d ug/m^3\n", CO2SensorResult, PMResult.PM2_5, PMResult.PM10);
	WriteFile();
	//WriteFile(filename);
	HAL_Delay(1000);
	
	return ;
 }

/* USER CODE END 0 */

int main(void){
	
  /* USER CODE BEGIN 1 */
	/* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_SDIO_SD_Init();
  MX_USART1_UART_Init();
  MX_USART2_UART_Init();
  MX_USART3_UART_Init();
  MX_FATFS_Init();
  MX_RTC_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */
	
  while (1){
    
		/* USER CODE BEGIN 3 */
		
		HAL_Delay(100);
		HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN);
		HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN);
		if(second_tmp != sTime.Seconds){
			second_tmp = sTime.Seconds;
			//printf("20%d%d-%d%d-%d%d\n", sDate.Year/10%10, sDate.Year%10, sDate.Month/10%10, sDate.Month%10, sDate.Date/10%10, sDate.Date%10);
			printf("[20%02d-%02d-%02d %02d:%02d:%02d] LOOP = %d\n",
				sDate.Year,
				sDate.Month,
				sDate.Date,
				sTime.Hours,
				sTime.Minutes,
				sTime.Seconds,
				TOT
			);
		}
		
		TOT++;
		LED0_on();
		LED1_on();
		
		CheckState();
		
		HAL_Delay(100);

  }
  /* USER CODE END 3 */
}
  • «
  • 1
  • »
Copyright © 2019-2022 spinmry. All rights reserved.
Except where otherwise noted, content on this blog is licensed under CC BY-SA 4.0.