秋招复盘——普通硕士做嵌入式也可以拿到50w年薪

本篇主要是作为刚刚结束了今年秋招的过来人,给学弟学妹们或还在找工作的朋友一些发自内心的建议,下面也附了我写过的一些大厂面经链接,真心希望可以帮到有需要的同学~
走过路过的朋友如果觉得还不错,麻烦点一个赞!拜托拜托~ 也欢迎随时留言或私信交流哈

个人背景

来自某电的普通211硕士,无背景无关系,学的是通信工程,实验室的研究方向也是通信相关的,而非嵌入式,也就是说我无论嵌入式还是软件开发都是野路子自学成才的...

秋招offer情况

大部分投递的是嵌入式,有些互联网公司则是后台软件开发,拿到华为、腾讯、美团、百度、大疆、字节跳动等20多家offer,其中绝大部分为sp或ssp,年薪超过40w的offer有10家以上,超过45w的offer有6家,超过50w的offer有3家。尽管我个人在我电肯定算不上能力靠前,但对我个人而言还算是一个比较满意的秋招(除了简历被阿里挂掉之外...),最终选择了去华为做芯片底层软件。

公司选择

在国产芯片和自动驾驶方兴未艾的时代,这对做嵌入式而言绝对是机会遍地的,可能秋招前只听过做嵌入式的有海思和大疆,结果一到找工作的时候发现这么多公司在都在搞嵌入式,工资还非常可观。

嵌入式岗位本质上还是软件为主的开发工作,无论卖手机卖飞机卖耳机的终端产品,还是做芯片的原厂,还是搞自动驾驶的新兴领域,都非常需要嵌入式工程师的加入;对于互联网公司来说,他们的操作系统业务或物联网业务都是与嵌入式相关的,也有互联网公司所支持的芯片部门。除此之外,如果软件基础扎实,其实对互联网后台开发也是可以尝试的,比如我曾经连A四道题外加深入聊了一波linux内核,也通过了字节后台开发的提前批面试,各种软件所运用的知识其实都是通透的。

前期准备

方法论

我个人提出一个观点:其实自从你想要找工作而不是读博或者继承家业的时候,就已经算“开始准备找工作”,因为做的每一件事情都对秋招的结果产生正负面的影响或者有一个逐渐积累的过程。举个例子——参加学科竞赛,我从本科开始参加各种电子设计类比赛,到找工作前一共拿了6个国家级竞赛的奖项,那个时候一直关注的都是“我从中可以学到什么?”;但是如果站在找工作的角度那就是“参加这个比赛可以向企业体现我什么能力?”。这其中就不仅仅是具体写了啥代码,做了啥功能,而是如何将这段真实的经历完整的提炼成一个可以展现自己处理问题的能力,“我做了什么功能”-->“我解决了什么问题”,其中设计的思路、debug的方法、验证的方法、突发奇想的瞬间,都是企业想去了解的东西。当带着这个思维去做事情,那么无论是做比赛、做项目、写论文,都是对找工作有促进作用的。

很多同学关注的一定是刷题,实话实说我临近找工作前的四月中旬才开始刷,牛客和leetcode加起来才刷了不到100道,而且都是比较基础简单的常见题。平心而论刷题并不是一个很重要的事情,只是说不能一点都不刷,至少见见各种题型还是有必要的。其实我个人不是很赞成几百上千道大量刷题的行为,原因有二:其一是在面试中算法能力的考验只占整个面试的一小部分内容,刷题的时间多了那么做其他准备工作的时间就少了;其二在定薪定级的时候,基本参考的依据主要还是获奖、项目、知识面、技术栈等,面试中的手撕代码只是作为一个抽查形式——能做对就行,至于这道题写的多漂亮并不是那么重要

除了刷题之外,更重要的事情是什么呢?首要的当然是知识积累,也就是看书学习,我个人更推荐去看书而不是去看面经博客,因为对于一个新的知识领域,建立对该领域知识体系的理解是比对某个细节知识点的记忆更重要的。举个例子——操作系统,不少的同学是看面经背诵式学习的,比如“操作系统的几种调度算法”、“发生死锁的必要条件”等,但是你觉得面试官是想听千篇一律的标准答案,还是想听到一个从实践出发、从设计模式出发、从横向对比出发的答案。我记得我学操作系统的时候,学法就很简单,首先制定一个目标——“我要写一个操作系统”,那么为了写这个OS就需要去纳百家之长,去看至少三个以上OS的设计思想和源码实现,并且去思考自己如果写一个新的OS创新点何在。其实这个过程也就两个月的业余时间就可以搞定,我相信经过这个过程足以让你在应对某一领域的提问时从容不迫。

不要相信那些去比较学java、学C++、学算法等哪个平均薪资更高的说法,不管学哪个领域只要学的好,公司都不会亏待你,搞单片机能搞出个花来一样可以拿很高的工资,相信一切事在人为。

学习路线

对嵌入式而言,看书一定是越早看越好,板子也一定是越早买越好,项目一定是做的越多越好

step1.买一块开发板

从来没听说过不碰板子就可以把嵌入式学好的,一旦买了板子就要学通透才对得起购买价值。有的人说是不是一定得买好的贵的,我觉得不一定,一块几十块钱的F103开发板就可以跑嵌入式操作系统,要弄懂操作系统在芯片上的很多细节,也是很值得深入研究的。当然在经济条件允许的情况下买一块片内和外设资源都比较丰富的开发板,也是对以后的扩展学习有帮助的,比如在MCU上尝试部署神经网络做图像识别等等。我自己主要用的开发板一共也就五块,stm32F103、stm32L496、stm32H750、imx6ull、树莓派,还有一些是参加活动公司寄过来的比如RISCV系列、zynq,或者一些定制化的板卡。其实板子玩多了就会发现没啥大区别,底层原理和方法都是那些,但要坚持自己手写每一行例程代码。如果是第一次买的话,个人推荐买正点原子的imx6ull,可以跑rtos也可以跑linux,外设也足够丰富,教程比较完善,可玩性高。

step2.开始玩开发板

不动手永远不知道事情本身的原理所在,建议是跟着各种操作系统开源社区来玩,无论是RT-Thread、TencentOS、LiteOS、AliOS等等,都是支持多种架构和开发板的OS社区,与嵌入式都是强相关的。在这里可以利用你手中的板卡,去做出自己的贡献,比如将某款OS移植到某个新架构或新的开发板上;为某款基础bsp去做更多外设的支持;为OS社区提出一个新的通用性组件包;修复一些别人提出但未解决的bug...在开源社区通过提出PR,和公司内部的人去沟通,让自己的代码被别人克隆使用,这是一件对自我很有提升的事情。如果不知道该怎么找项目,在学生阶段其实也是有机会去参加一些“有偿贡献”,比如GSoC、TencentSOC、中科院SOC等等,一个项目的奖金大概6000-2w不等,而且课题都比较具有挑战性。做成功一个完整的SOC对于学生来说不仅仅是项目经历和奖金的收获,更重要的是逐渐成为一个开源社区的长期参与者。这些经历在以后面试的时候会发现是多么的有用,我在面试的时候向不少面试官直接从github上展示我贡献的代码,行胜于言是最有说服力的

step3.多看书

无论做项目写代码再忙,每天也要留出一点时间看书,而且要有一定计划的去阅读。第一本书我推荐的是卡耐基梅隆的《深入理解计算机系统》,简称《csapp》,如何评价这本书?“读了它才觉得自己真的对计算机系统入门了!”,其实这本书我是大四看的,后来研究生的时候又读了一遍,里面每一章的配套实验也都很有心意,具体的无需多说,网上很多人好评如潮。第二本书开始,我个人认为就看自己了,当读完csapp后,其实就已经知道了该如何继续深入学习了。我推荐以下几个方向去学习:

  • 编程语言:C和C++,三件套《C和指针》、《C专家编程》、《C缺陷和陷阱》,C++我学的很一般就不发言了
  • 操作系统:找一个喜欢的rtos把源码看一遍、《UNIX环境高级编程》《linux内核完全注释》、《linux内核设计与实现》、《深入理解linux内核》
  • 硬件知识:无外乎裸机驱动+linux驱动,这个跟着板子的教程学就行,如果有机会接触一些更复杂的外设驱动则更好,比如:PCIE、USB、CAMERA等等
  • 其它:网络协议栈、神经网络加速、各种算法知识等等,根据机遇来学习

其实嵌入式涉及的知识是方方面面的,能把上面罗列的一些基础给学扎实已经很不错了,建立自己对知识的系统理解非常重要!我在面试的时候遇到很多从设计模式的角度去提问——“为什么这个模块别人要这么设计?”“针对一个特定的xxx场景下,如何修改原有的设计以至于发挥更好的效果?”,这些问题是最考验水平的加分项,书上不会直接讲这些,但书本里的知识可以给予你一个思考的起点去最大限度地回答这个问题。

step4.做项目

这里的项目指的不是开源社区贡献或者自己捣鼓的小项目,说的是那种真正应用在实际场景的项目,来源渠道可能是实验室接的、自己接的、实习做的或者其它地方搞来的等等。比如我做过至少两个比较完整的产品级项目,从需求分析到最后出货上线那种。真正做一个这种真枪实弹的项目是非常锻炼人的,怎样分解需求控制项目进度?面对需求变动怎么去迅速修改?如何做到突发情况预判和规避?如何快速定位bug并解决?如何用软件的方法去处理硬件的bug?对产品还有什么可以改进的地方?有哪些好的习惯对你做以后的项目有帮助?

这些东西其实是拉开和一般学生的差距,因为公司培养你获得基础知识其实很快,也不需要什么成本;但如果要掌握实际的项目经验,确实需要找师傅花时间带才可以学出来的。因此在学生时代尽量多做实际的项目,产生正向的价值,对嵌入式来说是非常重要的。

面试技巧

首先面试问啥,这个不用多说,网上面经写的很多很具体,可以对感兴趣的公司专门去搜索,面试多了无外乎基础知识都是那个范围之内的问题:比如芯片体系结构的知识、操作系统各种管理机制的细节、外设的驱动原理等等还有很多,都是通过看书或者后期查漏补缺可以学会的。这里谈到的面试技巧也一定是建立在本身基础扎实之上,巧妇难为无米之炊嘛。

首先是锻炼表达问题的方式,表达能力的问题每个人的基础不同,但归根结底都是用一套别人能理解的逻辑去说清楚如何解决问题。举个例子,面试官请你介绍一下某个项目:“本项目的背景是xxxx(我做这件事的动机)、项目要求是xxxx(我的功能目标)、具体功能分为哪几个模块(我的负责分工)、使用了什么关键技术(我的技术栈)、遇到了什么困难如何解决(我解决问题的能力)、取得了什么样的成果(我的产出和收获)”
其实如上6句话就可以很明白的把一个故事讲清楚,而且体现了自己多个维度的能力,面试官自然会对其中感兴趣的内容去做后续发问。可以在面试前对自己简历上的每一个比赛、项目、经历都像这6句话一样去思考一遍甚至先写下来,熟能生巧就越发自如。

然后是面对难解问题的回答,直接说不会当然不是最好的回答,意识到一个问题:面试官提出的难题并非是指望你完完全全真的解决它,你不会别人也不会,机会是均等的,那如何回答才可以让你在一众“不会的同学”中相对更好呢?“我首先将这个问题分解为1,2,3个阶段,先对它做一定的简化”、“我之前在其他地方遇到过类似但并不一样的场景,我认为可以将这种思维迁移过来”、“我知道他的一个或多个特定情况该如何解决,但普适情况还需要摸索”。这些技巧可以让你不至于完全愣住,但又可以体现出自己的思维能力和知识面,最重要的是能体现迁移学习的能力,这也是大公司最看重的能力——“你不会我们可以教,但你得是个聪明人学的足够快”。

最后就是每一次面试的总结,这个没啥多说的,及时查漏补缺就行。只是每次除了把不会的知识点弄懂之外,一个重要的思维是“如果下次别人换个问法,我能怎么样答的更系统更深入?”,有的人希望拿本子记下来,就像高中时期的错题集一样,但我觉得多花一点时间,对这个问题产生发散性的思维和系统的理解,是不太需要这么刻苦的记忆的,下次面试的时候是不是真懂,有水平的面试官很容易问出来。

个人总结

我在面试前,获得过6个国家级竞赛的奖项,RT-Thread的年度社区贡献之星,腾讯开源贡献者证书,三次SOC项目经历,两个企业产品级项目经历,其他无专利无论文,最后找工作也是一半运气、一半实力,总得来说秋招也算是正常发挥,情理之中。本身并不是嵌入式的研究方向或者说科班出身,主要靠自己凭兴趣琢磨捣鼓,相信大多数人都可以达到并超越我的水平。

面经

以下是我之前写过的还算不错的面经,都拿到了至少sp以上的offer,可以参考看看,因为时间原因,也有很多公司的面经没写

华为芯片底软:
https://www.nowcoder.com/discuss/711232?source_id=profile_create_nctrack&channel=-1

字节跳动后台开发:
https://www.nowcoder.com/discuss/687888?source_id=profile_create_nctrack&channel=-1

美团无人机嵌入式:
https://www.nowcoder.com/discuss/726642?source_id=profile_create_nctrack&channel=-1

大疆影像嵌入式:
https://www.nowcoder.com/discuss/730377?source_id=profile_create_nctrack&channel=-1

#我的秋招总结##秋招##学习路径##校招##书籍推荐##嵌入式工程师##C/C++#
全部评论
师兄牛皮啊
1 回复 分享
发布于 2021-10-27 10:48
大佬最后去了哪里?
1 回复 分享
发布于 2021-10-27 10:50
现在转 IC 还来得及吗🤣
1 回复 分享
发布于 2022-07-24 11:22
重新定义“普通”
25 回复 分享
发布于 2021-10-26 05:51
华子15a的普通硕士😅😅😅
8 回复 分享
发布于 2021-10-26 07:36
大佬太强了…😰😰
6 回复 分享
发布于 2021-10-25 23:13
看得我不好意思投了都😅
6 回复 分享
发布于 2021-10-27 11:13
大佬大佬,您可不普通。全面发展的优秀人才
5 回复 分享
发布于 2021-10-27 10:03
大佬谦虚了
3 回复 分享
发布于 2021-10-26 11:10
重铸芯片荣光,我辈义不容辞
2 回复 分享
发布于 2021-10-27 15:45
知识的储备、技能的深熟、书籍的理解、无一项可以匹配。咱都不好意思说咱也是搞嵌入式的啦,膜拜大佬😍
2 回复 分享
发布于 2021-10-27 16:14
师兄太强了
2 回复 分享
发布于 2021-10-28 16:36
大佬着实牛逼,榜样!
1 回复 分享
发布于 2021-10-27 11:31
哈哈 不错
1 回复 分享
发布于 2021-11-01 00:16
好强😁😁😁
1 回复 分享
发布于 2022-03-11 13:03
大佬你好,请问i.mx6ull上跑rtos的教程在哪可以找到?另外还想请教一下,如果仅有i.mx6ull开发板,没有其他硬件资源的话,可以做哪些项目?
1 回复 分享
发布于 2023-01-10 12:28 广东
大佬谦虚啊
点赞 回复 分享
发布于 2021-10-27 10:21
🎉恭喜牛友成功投稿【我的秋招总结】活动,并通过审核! ------------------- 分享你和秋招的那些事儿,赢取京东卡、牛客周边等奖励! 👉戳:https://www.nowcoder.com/discuss/775581 了解更多活动详情~
点赞 回复 分享
发布于 2021-10-27 11:43
大佬太强了
点赞 回复 分享
发布于 2021-10-27 16:00
太强了太强了,看了大佬的帖子,学到了好多,我是个小菜鸡。大佬帖子里的观点好多都感同身受,我也在努力做楼主帖子里的事,只是和楼主比起来,感觉差了一个档次,哈哈哈,加油加油,人外有人,我要向大佬学习!!
点赞 回复 分享
发布于 2021-11-01 07:37

相关推荐

3.内存管理&编程题(20道) 3.1由gcc编译的C语言程序占用的内存分为哪几个部分?栈区(stack)存放函数的参数、局部变量。堆区(heap)提供程序员动态申请的内存空间。全局(静态)区(static)存放全局变量和静态变量,初始化不为0的全局变量和静态变量、const型常量在一块区域(.data段),未初始化的、初始化为0的全局变量和静态变量在相邻的另一块区域(.bss段)。程序代码区存放函数体的二进制代码和字符串常量。3.2小端:一个数据的低位字节数据存储在低地址   大端:一个数据的高位字节数据存储在低地址   例如:int a=0x12345678;  //a首地址为0x200,大端存储格式如下:如何判读一个系统的大小端存储模式?(1)方法一:int *强制类型转换为char *,用"[]"解引用 void checkCpuMode(void)  {      int c = 0x12345678;      char *p = (char *)&c;      if(p[0] == 0x12)          printf("Big endian.");      else if(p[0] == 0x78)          printf("Little endian.");      else          printf("Uncertain.");  }  (2)方法二:int *强制类型转换为char *,用"*"解引用 void checkCpuMode(void)  {      int c = 0x12345678;      char *p = (char *)&c;      if(*p == 0x12)          printf("Big endian.");      else if(*p == 0x78)          printf("Little endian.");      else          printf("Uncertain.");  }  (3)方法三:包含short跟char的共用体 void checkCpuMode(void)  {      union Data      {          short a;          char b[sizeof(short)];      }data;      data.a = 0x1234;        if(data.b[0] == 0x12)          printf("Big endian.");      else if(data.b[0] == 0x34)          printf("Little endian.");      else          printf("uncertain.");  }  3.3全局变量和局部变量的区别?(1)全局变量储存在静态区,进入main函数之前就被创建,生命周期为整个源程序。 (2)局部变量在栈中分配,在函数被调用时才被创建,在函数退出时销毁,生命周期为函数内。 3.4以下程序中,主函数能否成功申请到内存空间?#include  #include  #include  void getmemory(char *p)  {      p = (char *)malloc(100);      strcpy(p, "hello world");  }  int main()  {      char *str = NULL;      getmemory(str);      printf("%s", str);      free(str);      return 0;  }  答案:不能。 解读:getmemory(str)没能改变str的值,因为传递给子函数的只是str的复制值NULL,main函数中的str一直都是 NULL。正确的getmemory()如下: ①传递的是二重指针,即str的指针void getmemory(char **p)   {      *p = (char *)malloc(100);      strcpy(*p, "hello world");  }  ②传递的是指针别名,即str的别名,C++中void getmemory(char * &p)   {      p = (char *)malloc(100);      strcpy(p, "hello world");  }  以上内容摘自专刊《嵌入式岗位笔试面试真题讲解》,该专刊不仅有真题讲解,还有经验分享,不清楚嵌入式该学什么的同学,想找嵌入式实习/正式工作的同学,都可以来看看:                  https://blog.nowcoder.net/zhuanlan/v0ELPM嵌入式公司推荐:   华为       、    小米         、     OPPO       、VIVO、     CVTE         、     大疆       、insta360影石、美的  、   TCL  、小米    、经纬恒润     、小鹏、 图森未来    、   百度    、滴滴、蔚来、理想、     联发科、 紫光展锐    、全志、   寒武纪    、晶晨半导体   、汇顶、华为     、 中兴    、浪潮    、TP-LINK、    讯飞、商汤、海康威视    、浙江   大华    、360。qi
查看4道真题和解析
点赞 评论 收藏
分享
评论
192
767
分享
牛客网
牛客企业服务