{"id":31649263,"url":"https://github.com/mytechnotalent/rp2350_blink_driver","last_synced_at":"2025-10-07T07:41:51.175Z","repository":{"id":318204367,"uuid":"1070344355","full_name":"mytechnotalent/RP2350_Blink_Driver","owner":"mytechnotalent","description":"An RP2350 blink driver written entirely in Assembler.","archived":false,"fork":false,"pushed_at":"2025-10-05T18:44:17.000Z","size":948,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-10-05T20:38:12.788Z","etag":null,"topics":["arm","armv8","assembler","assembler-code","assembler-implementation","assembly","blink","driver","embedded-systems","led","pico2","rp2350"],"latest_commit_sha":null,"homepage":"","language":"Assembly","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mytechnotalent.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-05T18:31:33.000Z","updated_at":"2025-10-05T18:44:21.000Z","dependencies_parsed_at":"2025-10-05T20:38:16.388Z","dependency_job_id":null,"html_url":"https://github.com/mytechnotalent/RP2350_Blink_Driver","commit_stats":null,"previous_names":["mytechnotalent/rp2350_blink_driver"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/mytechnotalent/RP2350_Blink_Driver","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mytechnotalent%2FRP2350_Blink_Driver","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mytechnotalent%2FRP2350_Blink_Driver/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mytechnotalent%2FRP2350_Blink_Driver/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mytechnotalent%2FRP2350_Blink_Driver/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mytechnotalent","download_url":"https://codeload.github.com/mytechnotalent/RP2350_Blink_Driver/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mytechnotalent%2FRP2350_Blink_Driver/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278740831,"owners_count":26037480,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-07T02:00:06.786Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["arm","armv8","assembler","assembler-code","assembler-implementation","assembly","blink","driver","embedded-systems","led","pico2","rp2350"],"created_at":"2025-10-07T07:41:49.615Z","updated_at":"2025-10-07T07:41:51.168Z","avatar_url":"https://github.com/mytechnotalent.png","language":"Assembly","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cimg src=\"https://github.com/mytechnotalent/RP2350_Blink_Driver/blob/main/RP2350_Blink_Driver.png?raw=true\"\u003e\n\n## FREE Reverse Engineering Self-Study Course [HERE](https://github.com/mytechnotalent/Reverse-Engineering-Tutorial)\n\n\u003cbr\u003e\n\n# RP2350 Blink Driver\nAn RP2350 blink driver written entirely in Assembler.\n\n# Code\n```assembler\n/**\n * FILE: main.s\n *\n * DESCRIPTION:\n * RP2350 Bare-Metal GPIO16 Blink, Coprocessor Version.\n * Minimal bare‑metal LED blink on the RP2350 using direct coprocessor\n * (MCRR) instructions to manipulate GPIO control registers. This bypasses\n * SDK abstractions and demonstrates register‑level control in assembler.\n *\n * AUTHOR: Kevin Thomas\n * CREATION DATE: October 5, 2025\n * UPDATE DATE: October 5, 2025\n */\n\n.syntax unified                                       // use unified assembly syntax\n.cpu cortex-m33                                       // target Cortex-M33 core\n.thumb                                                // use Thumb instruction set\n\n/**\n * Memory addresses and constants.\n */\n.equ IO_BANK0_BASE,   0x40028000                      // base address of IO_BANK0\n.equ PADS_BANK0_BASE, 0x40038000                      // base address of PADS_BANK0\n.equ SIO_BASE,        0xD0000000                      // base address of SIO block\n.equ GPIO16_CTRL,     0x84                            // io[16].ctrl offset\n.equ GPIO16_PAD,      0x44                            // pads io[16] offset\n.equ GPIO16_BIT,      (1\u003c\u003c16)                         // bit mask for GPIO16\n.equ GPIO_OUT_SET,    0x18                            // SIO-\u003eGPIO_OUT_SET offset\n.equ GPIO_OUT_XOR,    0x28                            // SIO-\u003eGPIO_OUT_XOR offset\n.equ GPIO_OE_SET,     0x38                            // SIO-\u003eGPIO_OE_SET offset\n.equ STACK_TOP,       0x20082000                      // top of non-secure SRAM\n.equ STACK_LIMIT,     0x2007A000                      // stack limit (32 KB below top)\n\n/**\n * Initialize the .vectors section. The .vectors section contains vector\n * table.\n */\n.section .vectors, \"ax\"                               // vector table section\n.align 2                                              // align to 4-byte boundary\n\n/**\n * Vector table section.\n */\n.global _vectors                                      // export symbol\n_vectors:\n  .word STACK_TOP                                     // initial stack pointer\n  .word Reset_Handler + 1                             // reset handler (Thumb bit set)\n\n/**\n * @brief   Reset handler for RP2350.\n *\n * @details Entry point after reset. Performs:\n *          - Stack initialization\n *          - Coprocessor enable\n *          - GPIO16 pad/function configuration\n *          - Branches to main() which contains the blink loop\n *\n * @param   None\n * @retval  None\n */\n.global Reset_Handler                                 // export Reset_Handler\n.type Reset_Handler, %function                        // mark as function\nReset_Handler:\n  BL    Init_Stack                                    // initialize MSP/PSP and limits\n  BL    Enable_Coprocessor                            // enable CP0 in CPACR for MCRR\n  B     main                                          // branch to main loop\n.size Reset_Handler, . - Reset_Handler\n\n/**\n * @brief   Initialize stack pointers.\n *\n * @details Sets Main and Process Stack Pointers (MSP/PSP) and their limits.\n *\n * @param   None\n * @retval  None\n */\n.type Init_Stack, %function\nInit_Stack:\n  LDR   R0, =STACK_TOP                                // load stack top\n  MSR   PSP, R0                                       // set PSP\n  LDR   R0, =STACK_LIMIT                              // load stack limit\n  MSR   MSPLIM, R0                                    // set MSP limit\n  MSR   PSPLIM, R0                                    // set PSP limit\n  LDR   R0, =STACK_TOP                                // reload stack top\n  MSR   MSP, R0                                       // set MSP\n  BX    LR                                            // return\n\n/**\n * @brief   Enable coprocessor access.\n *\n * @details Grants full access to coprocessor 0 (CP0) via CPACR.\n *\n * @param   None\n * @retval  None\n */\n.type Enable_Coprocessor , %function\nEnable_Coprocessor:\n  LDR   R0, =0xE000ED88                               // CPACR address\n  LDR   R1, [R0]                                      // read CPACR\n  ORR   R1, R1, #0x3                                  // set CP0 full access\n  STR   R1, [R0]                                      // write CPACR\n  DSB                                                 // data sync barrier\n  ISB                                                 // instruction sync barrier\n  BX    LR                                            // return\n\n/**\n * Initialize the .text section. \n * The .text section contains executable code.\n */\n.section .text                                        // code section\n.align 2                                              // align to 4-byte boundary\n\n/**\n * @brief   Main application entry point.\n *\n * @details Implements the infinite blink loop:\n *          - Set GPIO16 high\n *          - Delay ~500 ms\n *          - Set GPIO16 low\n *          - Delay ~500 ms\n *          - Repeat forever\n *\n * @param   None\n * @retval  None\n */\n.global main                                          // export main\n.type main, %function                                 // mark as function\nmain:\n.Push_Registers:\n  PUSH  {R4-R12, LR}                                  // push registers R4-R12, LR to the stack\n.GPIO16_Config:\n  BL    GPIO16_Config                                 // configure pads and FUNCSEL for GPIO16\n.Loop:\n  BL    GPIO16_Set                                    // set GPIO16 high\n  BL    Delay_500ms                                   // ~500 ms delay\n  BL    GPIO16_Clear                                  // set GPIO16 low\n  BL    Delay_500ms                                   // ~500 ms delay\n  B     Loop                                          // loop forever\n.Pop_Registers:\n  POP   {R4-R12, LR}                                  // pop registers R4-R12, LR from the stack\n  BX    LR                                            // return to caller\n\n/**\n * @brief   Configure GPIO16 for SIO control.\n *\n * @details Sets pad control (IE, OD, ISO) and FUNCSEL = 5 (SIO). Enables OE.\n *\n * @param   None\n * @retval  None\n */\n.type GPIO16_Config, %function\nGPIO16_Config:\n.GPIO16_Config_Push_Registers:\n  PUSH  {R4-R12, LR}                                  // push registers R4-R12, LR to the stack\n.GPIO16_Config_Modify_Pad:\n  LDR   R3, =PADS_BANK0_BASE + GPIO16_PAD             // pad control address\n  LDR   R2, [R3]                                      // read pad config\n  BIC   R2, R2, #0x80                                 // clear OD\n  ORR   R2, R2, #0x40                                 // set IE\n  BIC   R2, R2, #0x100                                // clear ISO\n  STR   R2, [R3]                                      // write pad config\n.GPIO16_Config_Modify_IO:\n  LDR   R3, =IO_BANK0_BASE + GPIO16_CTRL              // IO control address\n  LDR   R2, [R3]                                      // read IO config\n  BIC   R2, R2, #0x1F                                 // clear FUNCSEL\n  ORR   R2, R2, #5                                    // set FUNCSEL=5\n  STR   R2, [R3]                                      // write IO config\n.GPIO16_Config_Enable_OE:\n  MOVS  R4, #16                                       // GPIO number\n  MOVS  R5, #1                                        // enable output\n  MCRR  p0, #4, R4, R5, c4                            // gpioc_bit_oe_put(16, 1)\n.GPIO16_Config_Pop_Registers:\n  POP   {R4-R12, LR}                                  // pop registers R4-R12, LR from the stack\n  BX    LR                                            // return\n\n/**\n * @brief   Set GPIO16 high.\n *\n * @details Drives GPIO16 output = 1 via coprocessor MCRR.\n *\n * @param   None\n * @retval  None\n */\n.type GPIO16_Set, %function\nGPIO16_Set:\n.GPIO16_Set_Push_Registers:\n  PUSH  {R4-R12, LR}                                  // push registers R4-R12, LR to the stack\n.GPIO16_Set_Load_Operands:\n  MOVS  R4, #16                                       // GPIO number\n  MOVS  R5, #1                                        // logic high\n.GPIO16_Set_Execute:\n  MCRR  p0, #4, R4, R5, c0                            // gpioc_bit_out_put(16, 1)\n.GPIO16_Set_Pop_Registers:\n  POP   {R4-R12, LR}                                  // pop registers R4-R12, LR from the stack\n  BX    LR                                            // return to caller\n\n/**\n * @brief   Clear GPIO16 (set low).\n *\n * @details Drives GPIO16 output = 0 via coprocessor MCRR.\n *\n * @param   None\n * @retval  None\n */\n.type GPIO16_Clear, %function\nGPIO16_Clear:\n.GPIO16_Clear_Push_Registers:\n  PUSH  {R4-R12, LR}                                  // push registers R4-R12, LR to the stack\n.GPIO16_Clear_Load_Operands:\n  MOVS  R4, #16                                       // GPIO number\n  MOVS  R5, #0                                        // logic low\n.GPIO16_Clear_Execute:\n  MCRR  p0, #4, R4, R5, c0                            // gpioc_bit_out_put(16, 0)\n.GPIO16_Clear_Pop_Registers:\n  POP   {R4-R12, LR}                                  // pop registers R4-R12, LR from the stack\n  BX    LR                                            // return to caller\n\n/**\n * @brief   Busy‑wait Delay_500ms loop.\n *\n * @details Consumes ~2,000,000 cycles to approximate ~500 ms at boot clock.\n *\n * @param   None\n * @retval  None\n */\n.type Delay_500ms, %function\nDelay_500ms:\n.Delay_500ms_Push_Registers:\n  PUSH  {R4-R12, LR}                                  // push registers R4-R12, LR to the stack\n.Delay_500ms_Setup:\n  LDR   R2, =2000000                                  // loop count (~500 ms)\n.Delay_500ms_Loop:\n  SUBS  R2, R2, #1                                    // decrement counter\n  BNE   .Delay_500ms_Loop                             // branch until zero\n.Delay_500ms_Pop_Registers:\n  POP   {R4-R12, LR}                                  // pop registers R4-R12, LR from the stack\n  BX    LR                                            // return to caller\n\n/**\n * Test data and constants.\n * The .rodata section is used for constants and static data.\n */\n.section .rodata                                      // read-only data section\n\n/**\n * Initialized global data.\n * The .data section is used for initialized global or static variables.\n */\n.section .data                                        // data section\n\n/**\n * Uninitialized global data.\n * The .bss section is used for uninitialized global or static variables.\n */\n.section .bss                                         // BSS section\n```\n\n\u003cbr\u003e\n\n## License\n[Apache License 2.0](https://github.com/mytechnotalent/RP2350_Blink_Driver/blob/main/LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmytechnotalent%2Frp2350_blink_driver","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmytechnotalent%2Frp2350_blink_driver","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmytechnotalent%2Frp2350_blink_driver/lists"}