TinyOS2.x启动顺序

本文深入解析TinyOS2.x系统启动流程,包括平台初始化、调度器初始化、软件组件初始化等关键步骤。

对于嵌入式系统来说,系统的编译过程和启动顺序是至关重要的,对这两部分的了解程度直接关系到对系统移植、裁剪和配置的相关操作。在这篇文章中我们来看一看TinyOS2.x是如何启动的。需要强调的是,这里所涉及的系统版本是2.x而不是1.x,这两个版本还是有很大的区别的。

TinyOS2.x的启动代码其实很清晰的,其具体的实现代码在tinyos2.x/tos/system/RealMainP.nc中:

int main() @C() @spontaneous() {
atomic
{
platform_bootstrap();

call Scheduler.init();

call PlatformInit.init();


while (call Scheduler.runNextTask());

call SoftwareInit.init();


while (call Scheduler.runNextTask());
}

__nesc_enable_interrupt();

signal Boot.booted();

call Scheduler.taskLoop();

return -1;
}

组件RealMainP是被同一目录下的MainC组件调用的(几乎每个应用在顶层配置文件中都会引入MainC组件的)。下面我们详细分析下RealMainP模块中的内容。

首先,该模块中的main()函数是自发运行的,当然该函数也是系统启动的入口。

platform_bootstrap():这是系统调用的第一个命令,主要用于配置内存系统和设置处理器的工作模式。但通常情况下该函数为空。头文件tinyos2.1/tos/syetem/tos.h中包含了该函数的默认实现,即不做任何操作。如果某个平台需要将这个默认实现换成其他的具体操作,可以在该平台的platform.h文件里用#define语句声明。

Scheduler.init():调度器初始化。

PlatformInit.init():平台初始化(可以参考前面的文章《TinyOS之Blink(二) - Platform初始化分析》)。

while (call Scheduler.runNextTask()):检测初始化过程中是否有任务发布,如果有就先执行任务。

SoftwareInit.init():不直接依赖于硬件资源的组件初始化都应绑定Init(SoftwareInit接口是Init接口的别名)接口到MainC组件的SoftwareInit接口(但在tinyos2.1中并为找到Init接口的具体实现,也就是说Init接口是和哪一个模块进行绑定的?)。

__nesc_enable_interrupt():中断使能。

signal Boot.booted():这个booted事件就类似于用户角度的main函数,是实际应用程序的入口。

call Scheduler.taskLoop():循环运行任务调度器。

至此,系统启动完毕。

```python import pygame import random import json import os from datetime import datetime # 初始化 pygame.init() pygame.font.init() # 颜色定义 white = (255, 255, 255) black = (0, 0, 0) red = (213, 50, 80) green_head = (0, 100, 0) green_body = (0, 200, 0) blue = (50, 153, 213) gray = (200, 200, 200) dark_gray = (100, 100, 100) gold = (255, 215, 0) # bg_color = (70, 130, 180) # 钢蓝色 # bg_color = (240, 248, 255) # 爱丽丝蓝 # bg_color = (220, 245, 220) # 淡绿色 bg_color = (255, 248, 220) # 柯林斯黄(米白) # bg_color = (30, 30, 30) # 深灰(暗色模式) # 屏幕尺寸 width = 800 height = 600 # 格子类型标识 EMPTY = 0 SNAKE_BODY = 1 WALL = 2 FOOD = 3 # 字体 font_title = pygame.font.SysFont("simhei", 72) font_small = pygame.font.SysFont("simhei", 28) font_tiny = pygame.font.SysFont("simhei", 22) # 记录文件 RECORD_FILE = "snake_records.json" class Snake: def __init__(self, block_size=20): self.block_size = block_size self.direction = 'RIGHT' self.change_to = 'RIGHT' # 初始位置 self.head_x = width // 2 // block_size * block_size self.head_y = height // 2 // block_size * block_size self.body = [[self.head_x, self.head_y]] self.length = 1 # 初始基础速度 self.base_speed = 5 self.max_speed = 15 # 防止太快无法操作 @property def speed(self): """动态计算当前速度:基于长度增长""" added_speed = (self.length - 1) // 3 # 每3段加1速 return min(self.base_speed + added_speed, self.max_speed) def update_direction(self): """根据输入更新方向(防止反向)""" if self.change_to == 'UP' and self.direction != 'DOWN': self.direction = 'UP' elif self.change_to == 'DOWN' and self.direction != 'UP': self.direction = 'DOWN' elif self.change_to == 'LEFT' and self.direction != 'RIGHT': self.direction = 'LEFT' elif self.change_to == 'RIGHT' and self.direction != 'LEFT': self.direction = 'RIGHT' def move(self): """移动蛇头并更新身体""" x_change = y_change = 0 if self.direction == 'UP': y_change = -self.block_size elif self.direction == 'DOWN': y_change = self.block_size elif self.direction == 'LEFT': x_change = -self.block_size elif self.direction == 'RIGHT': x_change = self.block_size new_head = [self.head_x + x_change, self.head_y + y_change] self.body.append(new_head) if len(self.body) > self.length: del self.body[0] self.head_x, self.head_y = new_head def grow(self): """增加长度""" self.length += 1 def check_collision(self): head_x, head_y = self.head_x, self.head_y grid_x, grid_y = head_x // self.block_size, head_y // self.block_size # 检查是否撞墙 or 自己 if self.game_map.is_blocked(grid_x, grid_y): return True # 可选:检查超出屏幕(但上面 is_blocked 已包括边界) return False def draw(self, screen): """绘制蛇""" for part in self.body[:-1]: pygame.draw.rect(screen, green_body, [*part, self.block_size, self.block_size]) # 头部 head = self.body[-1] pygame.draw.rect(screen, green_head, [*head, self.block_size, self.block_size]) class Food: def __init__(self, block_size=20): self.block_size = block_size self.x = 0 self.y = 0 self.color = red def spawn(self, game_map): """让地图分配一个新的食物位置""" pos = game_map.place_food() if pos: self.x, self.y = pos def draw(self, screen): rect = pygame.Rect(self.x, self.y, self.block_size, self.block_size) pygame.draw.rect(screen, self.color, rect) class Leaderboard: """排行榜类:加载、保存、排序记录""" def __init__(self, filename=RECORD_FILE): self.filename = filename self.records = self.load() def load(self): if not os.path.exists(self.filename): return [] try: with open(self.filename, 'r', encoding='utf-8') as f: data = json.load(f) for item in data: if "name" not in item: item["name"] = "无名" return sorted(data, key=lambda x: x["score"], reverse=True) except Exception as e: print("加载排行榜失败:", e) return [] def save(self, score, length, name="无名"): new_record = { "name": name, "score": score, "length": length, "timestamp": datetime.now().isoformat() } self.records.append(new_record) self.records = sorted(self.records, key=lambda x: x["score"], reverse=True)[:50] with open(self.filename, 'w', encoding='utf-8') as f: json.dump(self.records, f, ensure_ascii=False, indent=2) def top(self, n=5): return self.records[:n] def best(self): return self.records[0] if self.records else None class GameMap: def __init__(self, width_in_blocks, height_in_blocks): self.width = width_in_blocks self.height = height_in_blocks self.block_size = 20 # 与 Snake 和 Food 一致 self.grid = [[EMPTY for _ in range(self.width)] for _ in range(self.height)] # 墙体列表(保存 (x, y) 坐标) self.walls = [] self._create_walls() def _create_walls(self): """创建边界墙 + 中央装饰性墙体""" # 边界墙(四周) for x in range(self.width): self._add_wall(x, 0) self._add_wall(x, self.height - 1) for y in range(self.height): self._add_wall(0, y) self._add_wall(self.width - 1, y) # 可选:中间加一些障碍 for i in range(5, 10): self._add_wall(10, i) for i in range(15, 20): self._add_wall(i, 10) def _add_wall(self, x, y): """内部添加墙并更新 grid""" if 0 <= x < self.width and 0 <= y < self.height: self.walls.append((x, y)) self.grid[y][x] = WALL def is_blocked(self, x, y): """ 判断某个格子是否被占用(不能移动到) :param x: 格子列(以 block 为单位) :param y: 格子行 :return: True 表示无法进入 """ if not (0 <= x < self.width and 0 <= y < self.height): return True # 超出边界 return self.grid[y][x] in [WALL, SNAKE_BODY] def place_food(self): """ 在空地上随机放置食物 :return: (x, y) 食物位置(像素级) """ available = [] for y in range(self.height): for x in range(self.width): if self.grid[y][x] == EMPTY: available.append((x, y)) if not available: return None fx, fy = random.choice(available) self.grid[fy][fx] = FOOD return fx * self.block_size, fy * self.block_size def update_snake_position(self, snake_body): """ 用当前蛇身更新地图标记 :param snake_body: 蛇身体列表 [(x1,y1), ...](像素坐标) """ # 先清除旧的蛇身标记 for y in range(self.height): for x in range(self.width): if self.grid[y][x] == SNAKE_BODY: self.grid[y][x] = EMPTY # 重新标记蛇身(跳过头部?或包含全部) for part in snake_body[:-1]: # 排除尾部?这里可以调整策略 sx, sy = part[0] // self.block_size, part[1] // self.block_size if 0 <= sx < self.width and 0 <= sy < self.height: self.grid[sy][sx] = SNAKE_BODY def draw(self, screen): """绘制墙体""" wall_color = (80, 80, 80) # 灰色墙体 for x, y in self.walls: rect = pygame.Rect(x * self.block_size, y * self.block_size, self.block_size, self.block_size) pygame.draw.rect(screen, wall_color, rect) # 可选:加边框 pygame.draw.rect(screen, (50, 50, 50), rect, border_width=2) class UI: """用户界面类:负责所有文字渲染""" def __init__(self, screen): self.screen = screen self.font_title = font_title self.font_small = font_small self.font_tiny = font_tiny def message_center(self, msg, color, y_offset=0, font=None): font = font or self.font_small text = font.render(msg, True, color) rect = text.get_rect(center=(width // 2, height // 2 + y_offset)) self.screen.blit(text, rect) def your_score(self, score, length): text = self.font_small.render(f"得分: {score} | 长度: {length}", True, black) self.screen.blit(text, (10, 10)) def show_start_screen(self, leaderboard): self.screen.fill(bg_color) # 标题 title = self.font_title.render("🐍 贪吃蛇", True, green_head) title_rect = title.get_rect(center=(width // 2, 180)) self.screen.blit(title, title_rect) # 开始提示 start_msg = self.font_small.render("按 【空格键】 开始游戏", True, black) start_rect = start_msg.get_rect(center=(width // 2, height // 2)) self.screen.blit(start_msg, start_rect) # 最高分展示 best = leaderboard.best() if best: best_text = self.font_small.render(f"🏆 最高分: {best['score']} ({best['name']})", True, gold) best_rect = best_text.get_rect(center=(width // 2, height - 250)) self.screen.blit(best_text, best_rect) # 排行榜标题 leader_title = self.font_tiny.render("🎮 近期高手榜", True, black) leader_rect = leader_title.get_rect(center=(width // 2, height - 210)) self.screen.blit(leader_title, leader_rect) # Top 5 列表 y_start = height - 180 line_height = 28 for i, game in enumerate(leaderboard.top(5)): color = gold if i == 0 else (blue if i == 1 else dark_gray) name_display = game["name"][:6] + "..." if len(game["name"]) > 6 else game["name"] text = self.font_tiny.render(f"{i + 1}. {name_display:<7} — {game['score']:>3}分", True, color) rect = text.get_rect(center=(width // 2, y_start + i * line_height)) if rect.bottom <= height - 10: self.screen.blit(text, rect) def game_over_screen(self, score, length, leaderboard, on_get_name): name = on_get_name() # 回调获取名字 leaderboard.save(score, length, name) records = leaderboard.records while True: self.screen.fill(bg_color) self.message_center("游戏结束!", red, -180, self.font_title) self.your_score(score, length) current_text = self.font_small.render(f"🎮 {name},你得了 {score} 分!", True, green_head) self.screen.blit(current_text, (width // 2 - current_text.get_width() // 2, height // 2 - 60)) if records: best_entry = records[0] best_line = self.font_small.render(f"🏆 最高分: {best_entry['score']} ({best_entry['name']})", True, gold) self.screen.blit(best_line, (width // 2 - best_line.get_width() // 2, height // 2 - 20)) y_offset = height // 2 + 25 for i, game in enumerate(records[:5]): color = gold if i == 0 else (blue if game["name"] == name else dark_gray) text = self.font_tiny.render( f"{i+1:2d}. {game['name']:<8} — {game['score']:>3}分 (长度{game['length']})", True, color) rect = text.get_rect(center=(width // 2, y_offset)) self.screen.blit(text, rect) y_offset += 30 self.message_center("按【C键】重新开始", black, 140) self.message_center("按【Q键】退出游戏", black, 170) pygame.display.update() for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() quit() if event.type == pygame.KEYDOWN: if event.key == pygame.K_c: return True elif event.key == pygame.K_q: return False class GameController: def __init__(self): self.width = width self.height = height self.screen = pygame.display.set_mode((width, height)) pygame.display.set_caption('🐍 贪吃蛇') self.block_size = 20 cols = self.width // self.block_size rows = self.height // self.block_size self.game_map = GameMap(cols, rows) self.food = Food(self.block_size) self.snake = Snake(self.block_size, self.game_map) # 传入 map self.clock = pygame.time.Clock() self.ui = UI(self.screen) # self.leaderboard = LeaderBoard("scores.json") def reset_game(self): self.snake = Snake() self.food = Food() self.game_over = False def show_start_screen(self): """✅ 新增:显示主菜单界面""" while True: self.ui.show_start_screen(self.leaderboard) pygame.display.update() for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() quit() if event.type == pygame.KEYDOWN: if event.key == pygame.K_SPACE: return # 进入游戏 def get_player_name(self): name = "" max_length = 10 input_active = True while input_active: self.screen.fill(bg_color) # ✅ 每次清屏 # 提示文字 prompt = font_small.render("请输入你的名字:", True, black) self.screen.blit(prompt, (width // 2 - prompt.get_width() // 2, height // 2 - 100)) # 输入框 input_area = pygame.Rect(width // 2 - 150, height // 2 - 30, 300, 60) pygame.draw.rect(self.screen, gray, input_area, border_radius=8) pygame.draw.rect(self.screen, black, input_area, width=2, border_radius=8) # 当前输入内容 display_text = name if name else "点击这里输入..." text_surface = font_small.render(display_text, True, black if name else dark_gray) self.screen.blit(text_surface, (input_area.x + 10, input_area.y + 10)) # 提示信息 hint1 = font_tiny.render("支持中文/英文 | 最多10字符", True, dark_gray) hint2 = font_tiny.render("回车确认,退格删除", True, dark_gray) self.screen.blit(hint1, (width // 2 - hint1.get_width() // 2, height // 2 + 60)) self.screen.blit(hint2, (width // 2 - hint2.get_width() // 2, height // 2 + 90)) pygame.display.flip() for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() quit() if event.type == pygame.KEYDOWN: if event.key in [pygame.K_RETURN, pygame.K_KP_ENTER]: input_active = False elif event.key == pygame.K_BACKSPACE: name = name[:-1] else: char = event.unicode if char.isprintable() and not char.isspace() and len(name) < max_length: name += char return name.strip() or "无名" def run(self): while True: self.ui.show_start_screen(self.leaderboard) self.reset_game() self.food.spawn(self.game_map) # 第一次生成食物 while not self.game_over: keys = pygame.key.get_pressed() # 方向控制... if keys[pygame.K_UP]: self.snake.change_to = 'UP' if keys[pygame.K_DOWN]: self.snake.change_to = 'DOWN' if keys[pygame.K_LEFT]: self.snake.change_to = 'LEFT' if keys[pygame.K_RIGHT]: self.snake.change_to = 'RIGHT' for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() quit() self.snake.update_direction() self.snake.move() # 更新地图中的蛇身标记 self.game_map.update_snake_position(self.snake.body) # 吃食物 if self.snake.head_x == self.food.x and self.snake.head_y == self.food.y: self.snake.grow() self.food.spawn(self.game_map) # 通知地图重新生成 if self.snake.check_collision(): self.game_over = True # 绘制 self.screen.fill(bg_color) self.game_map.draw(self.screen) self.food.draw(self.screen) self.snake.draw(self.screen) self.ui.your_score(self.snake.length - 1, self.snake.length) pygame.display.update() self.clock.tick(self.snake.speed) # 启动游戏 if __name__ == "__main__": game = GameController() game.run() ``` 帮我修改程序当中的错误
11-07
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值